|  | 
| 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