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