|  | 
| 1 |  | -use rustc_hir as hir; | 
|  | 1 | +use rustc_hir::{self as hir, LangItem}; | 
| 2 | 2 | use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes}; | 
| 3 | 3 | use rustc_infer::traits::{ImplSource, Obligation, PredicateObligation}; | 
| 4 | 4 | use rustc_middle::span_bug; | 
| @@ -46,6 +46,12 @@ pub fn evaluate_host_effect_obligation<'tcx>( | 
| 46 | 46 |         Err(EvaluationFailure::NoSolution) => {} | 
| 47 | 47 |     } | 
| 48 | 48 | 
 | 
|  | 49 | +    match evaluate_host_effect_from_builtin_impls(selcx, obligation) { | 
|  | 50 | +        Ok(result) => return Ok(result), | 
|  | 51 | +        Err(EvaluationFailure::Ambiguous) => return Err(EvaluationFailure::Ambiguous), | 
|  | 52 | +        Err(EvaluationFailure::NoSolution) => {} | 
|  | 53 | +    } | 
|  | 54 | + | 
| 49 | 55 |     match evaluate_host_effect_from_selection_candiate(selcx, obligation) { | 
| 50 | 56 |         Ok(result) => return Ok(result), | 
| 51 | 57 |         Err(EvaluationFailure::Ambiguous) => return Err(EvaluationFailure::Ambiguous), | 
| @@ -226,6 +232,105 @@ fn evaluate_host_effect_from_item_bounds<'tcx>( | 
| 226 | 232 |     } | 
| 227 | 233 | } | 
| 228 | 234 | 
 | 
|  | 235 | +fn evaluate_host_effect_from_builtin_impls<'tcx>( | 
|  | 236 | +    selcx: &mut SelectionContext<'_, 'tcx>, | 
|  | 237 | +    obligation: &HostEffectObligation<'tcx>, | 
|  | 238 | +) -> Result<ThinVec<PredicateObligation<'tcx>>, EvaluationFailure> { | 
|  | 239 | +    match selcx.tcx().as_lang_item(obligation.predicate.def_id()) { | 
|  | 240 | +        Some(LangItem::Destruct) => evaluate_host_effect_for_destruct_goal(selcx, obligation), | 
|  | 241 | +        // Some(LangItem::Fn | LangItem::FnMut | LangItem::FnOnce) => | 
|  | 242 | +        _ => Err(EvaluationFailure::NoSolution), | 
|  | 243 | +    } | 
|  | 244 | +} | 
|  | 245 | + | 
|  | 246 | +// NOTE: Keep this in sync with `const_conditions_for_destruct` in the new solver. | 
|  | 247 | +fn evaluate_host_effect_for_destruct_goal<'tcx>( | 
|  | 248 | +    selcx: &mut SelectionContext<'_, 'tcx>, | 
|  | 249 | +    obligation: &HostEffectObligation<'tcx>, | 
|  | 250 | +) -> Result<ThinVec<PredicateObligation<'tcx>>, EvaluationFailure> { | 
|  | 251 | +    let tcx = selcx.tcx(); | 
|  | 252 | +    let destruct_def_id = tcx.require_lang_item(LangItem::Destruct, None); | 
|  | 253 | +    let self_ty = obligation.predicate.self_ty(); | 
|  | 254 | + | 
|  | 255 | +    let const_conditions = match *self_ty.kind() { | 
|  | 256 | +        // An ADT is `~const Destruct` only if all of the fields are, | 
|  | 257 | +        // *and* if there is a `Drop` impl, that `Drop` impl is also `~const`. | 
|  | 258 | +        ty::Adt(adt_def, args) => { | 
|  | 259 | +            let mut const_conditions: ThinVec<_> = adt_def | 
|  | 260 | +                .all_fields() | 
|  | 261 | +                .map(|field| ty::TraitRef::new(tcx, destruct_def_id, [field.ty(tcx, args)])) | 
|  | 262 | +                .collect(); | 
|  | 263 | +            match adt_def.destructor(tcx).map(|dtor| dtor.constness) { | 
|  | 264 | +                // `Drop` impl exists, but it's not const. Type cannot be `~const Destruct`. | 
|  | 265 | +                Some(hir::Constness::NotConst) => return Err(EvaluationFailure::NoSolution), | 
|  | 266 | +                // `Drop` impl exists, and it's const. Require `Ty: ~const Drop` to hold. | 
|  | 267 | +                Some(hir::Constness::Const) => { | 
|  | 268 | +                    let drop_def_id = tcx.require_lang_item(LangItem::Drop, None); | 
|  | 269 | +                    let drop_trait_ref = ty::TraitRef::new(tcx, drop_def_id, [self_ty]); | 
|  | 270 | +                    const_conditions.push(drop_trait_ref); | 
|  | 271 | +                } | 
|  | 272 | +                // No `Drop` impl, no need to require anything else. | 
|  | 273 | +                None => {} | 
|  | 274 | +            } | 
|  | 275 | +            const_conditions | 
|  | 276 | +        } | 
|  | 277 | + | 
|  | 278 | +        ty::Array(ty, _) | ty::Pat(ty, _) | ty::Slice(ty) => { | 
|  | 279 | +            thin_vec![ty::TraitRef::new(tcx, destruct_def_id, [ty])] | 
|  | 280 | +        } | 
|  | 281 | + | 
|  | 282 | +        ty::Tuple(tys) => { | 
|  | 283 | +            tys.iter().map(|field_ty| ty::TraitRef::new(tcx, destruct_def_id, [field_ty])).collect() | 
|  | 284 | +        } | 
|  | 285 | + | 
|  | 286 | +        // Trivially implement `~const Destruct` | 
|  | 287 | +        ty::Bool | 
|  | 288 | +        | ty::Char | 
|  | 289 | +        | ty::Int(..) | 
|  | 290 | +        | ty::Uint(..) | 
|  | 291 | +        | ty::Float(..) | 
|  | 292 | +        | ty::Str | 
|  | 293 | +        | ty::RawPtr(..) | 
|  | 294 | +        | ty::Ref(..) | 
|  | 295 | +        | ty::FnDef(..) | 
|  | 296 | +        | ty::FnPtr(..) | 
|  | 297 | +        | ty::Never | 
|  | 298 | +        | ty::Infer(ty::InferTy::FloatVar(_) | ty::InferTy::IntVar(_)) | 
|  | 299 | +        | ty::Error(_) => thin_vec![], | 
|  | 300 | + | 
|  | 301 | +        // Coroutines and closures could implement `~const Drop`, | 
|  | 302 | +        // but they don't really need to right now. | 
|  | 303 | +        ty::Closure(_, _) | 
|  | 304 | +        | ty::CoroutineClosure(_, _) | 
|  | 305 | +        | ty::Coroutine(_, _) | 
|  | 306 | +        | ty::CoroutineWitness(_, _) => return Err(EvaluationFailure::NoSolution), | 
|  | 307 | + | 
|  | 308 | +        // FIXME(unsafe_binders): Unsafe binders could implement `~const Drop` | 
|  | 309 | +        // if their inner type implements it. | 
|  | 310 | +        ty::UnsafeBinder(_) => return Err(EvaluationFailure::NoSolution), | 
|  | 311 | + | 
|  | 312 | +        ty::Dynamic(..) | ty::Param(_) | ty::Alias(..) | ty::Placeholder(_) | ty::Foreign(_) => { | 
|  | 313 | +            return Err(EvaluationFailure::NoSolution); | 
|  | 314 | +        } | 
|  | 315 | + | 
|  | 316 | +        ty::Bound(..) | 
|  | 317 | +        | ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => { | 
|  | 318 | +            panic!("unexpected type `{self_ty:?}`") | 
|  | 319 | +        } | 
|  | 320 | +    }; | 
|  | 321 | + | 
|  | 322 | +    Ok(const_conditions | 
|  | 323 | +        .into_iter() | 
|  | 324 | +        .map(|trait_ref| { | 
|  | 325 | +            obligation.with( | 
|  | 326 | +                tcx, | 
|  | 327 | +                ty::Binder::dummy(trait_ref) | 
|  | 328 | +                    .to_host_effect_clause(tcx, obligation.predicate.constness), | 
|  | 329 | +            ) | 
|  | 330 | +        }) | 
|  | 331 | +        .collect()) | 
|  | 332 | +} | 
|  | 333 | + | 
| 229 | 334 | fn evaluate_host_effect_from_selection_candiate<'tcx>( | 
| 230 | 335 |     selcx: &mut SelectionContext<'_, 'tcx>, | 
| 231 | 336 |     obligation: &HostEffectObligation<'tcx>, | 
|  | 
0 commit comments