@@ -5,9 +5,10 @@ use std::iter;
55use crate :: traits:: TupleArgumentsFlag ;
66
77use super :: assembly:: { self , AssemblyCtxt } ;
8- use super :: { CanonicalGoal , Certainty , EvalCtxt , Goal , QueryResult } ;
8+ use super :: { CanonicalGoal , Certainty , EvalCtxt , Goal , MaybeCause , QueryResult } ;
9+
910use rustc_hir:: def_id:: DefId ;
10- use rustc_hir:: Unsafety ;
11+ use rustc_hir:: { Movability , Mutability , Unsafety } ;
1112use rustc_infer:: infer:: { InferCtxt , InferOk , LateBoundRegionConversionTime } ;
1213use rustc_infer:: traits:: query:: NoSolution ;
1314use rustc_infer:: traits:: util:: supertraits;
@@ -225,20 +226,9 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
225226 ) {
226227 // FIXME: We need to give auto trait candidates less precedence than impl candidates?
227228 acx. infcx . probe ( |_| {
228- let Ok ( constituent_tys) =
229- instantiate_constituent_tys_for_auto_trait ( acx. infcx , goal. predicate . self_ty ( ) ) else { return } ;
230- let nested_goals = constituent_tys
231- . into_iter ( )
232- . map ( |ty| {
233- Goal :: new (
234- acx. cx . tcx ,
235- goal. param_env ,
236- ty:: Binder :: dummy ( goal. predicate . with_self_ty ( acx. cx . tcx , ty) ) ,
237- )
238- } )
239- . collect ( ) ;
240- let Ok ( certainty) = acx. cx . evaluate_all ( acx. infcx , nested_goals) else { return } ;
241- acx. try_insert_candidate ( CandidateSource :: AutoImpl , certainty) ;
229+ let components =
230+ instantiate_constituent_tys_for_auto_trait ( acx. infcx , goal. predicate . self_ty ( ) ) ;
231+ evaluate_goal_for_components ( acx, goal, components, CandidateSource :: AutoImpl ) ;
242232 } )
243233 }
244234
@@ -284,36 +274,51 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
284274 let self_ty = goal. predicate . self_ty ( ) ;
285275
286276 if Some ( trait_def_id) == lang_items. sized_trait ( ) {
287- if self_ty. is_trivially_sized ( acx. cx . tcx ) {
288- acx. try_insert_candidate ( CandidateSource :: Builtin , Certainty :: Yes ) ;
289- }
277+ acx. infcx . probe ( |_| {
278+ let components = instantiate_constituent_tys_for_sized_trait ( acx. infcx , self_ty) ;
279+ evaluate_goal_for_components ( acx, goal, components, CandidateSource :: Builtin ) ;
280+ } )
290281 } else if Some ( trait_def_id) == lang_items. copy_trait ( )
291282 || Some ( trait_def_id) == lang_items. clone_trait ( )
292283 {
293- // FIXME
284+ acx. infcx . probe ( |_| {
285+ let components =
286+ instantiate_constituent_tys_for_copy_clone_trait ( acx. infcx , self_ty) ;
287+ evaluate_goal_for_components ( acx, goal, components, CandidateSource :: Builtin ) ;
288+ } )
294289 } else if Some ( trait_def_id) == lang_items. discriminant_kind_trait ( )
295290 || Some ( trait_def_id) == lang_items. pointee_trait ( )
296291 {
297292 // `Pointee` and `DiscriminantKind` are implemented by all traits unconditionally
298293 acx. try_insert_candidate ( CandidateSource :: Builtin , Certainty :: Yes ) ;
299294 } else if Some ( trait_def_id) == lang_items. tuple_trait ( ) {
300295 match * self_ty. kind ( ) {
301- ty:: Infer ( ty:: TyVar ( _) ) => todo ! ( "ambiguous" ) ,
296+ ty:: Infer ( ty:: TyVar ( _) ) => acx. try_insert_candidate (
297+ CandidateSource :: Builtin ,
298+ Certainty :: Maybe ( MaybeCause :: Ambiguity ) ,
299+ ) ,
302300 ty:: Tuple ( _) => acx. try_insert_candidate ( CandidateSource :: Builtin , Certainty :: Yes ) ,
303301 _ => { }
304302 }
305303 } else if Some ( trait_def_id) == lang_items. pointer_sized ( ) {
306304 let erased_self_ty = acx. cx . tcx . erase_regions ( self_ty) ;
307305 if erased_self_ty. has_non_region_infer ( ) {
308- todo ! ( "ambiguous" )
309- }
310- let usize_layout =
311- acx. cx . tcx . layout_of ( ty:: ParamEnv :: empty ( ) . and ( acx. cx . tcx . types . usize ) ) . unwrap ( ) ;
312- if let Ok ( layout) = acx. cx . tcx . layout_of ( goal. param_env . and ( self_ty) )
313- && layout. layout . size ( ) == usize_layout. layout . size ( )
314- && layout. layout . align ( ) . abi == usize_layout. layout . align ( ) . abi
315- {
316- acx. try_insert_candidate ( CandidateSource :: Builtin , Certainty :: Yes ) ;
306+ acx. try_insert_candidate (
307+ CandidateSource :: Builtin ,
308+ Certainty :: Maybe ( MaybeCause :: Ambiguity ) ,
309+ )
310+ } else {
311+ let usize_layout = acx
312+ . cx
313+ . tcx
314+ . layout_of ( ty:: ParamEnv :: empty ( ) . and ( acx. cx . tcx . types . usize ) )
315+ . unwrap ( ) ;
316+ if let Ok ( layout) = acx. cx . tcx . layout_of ( goal. param_env . and ( self_ty) )
317+ && layout. layout . size ( ) == usize_layout. layout . size ( )
318+ && layout. layout . align ( ) . abi == usize_layout. layout . align ( ) . abi
319+ {
320+ acx. try_insert_candidate ( CandidateSource :: Builtin , Certainty :: Yes ) ;
321+ }
317322 }
318323 } else if Some ( trait_def_id) == lang_items. coerce_unsized_trait ( )
319324 || Some ( trait_def_id) == lang_items. unsize_trait ( )
@@ -327,7 +332,7 @@ fn match_poly_trait_ref_against_goal<'tcx>(
327332 acx : & mut AssemblyCtxt < ' _ , ' tcx , TraitPredicate < ' tcx > > ,
328333 goal : Goal < ' tcx , TraitPredicate < ' tcx > > ,
329334 trait_ref : ty:: PolyTraitRef < ' tcx > ,
330- candidate : impl FnOnce ( ) -> CandidateSource ,
335+ candidate : CandidateSource ,
331336) {
332337 acx. infcx . probe ( |_| {
333338 let trait_ref = acx. infcx . replace_bound_vars_with_fresh_vars (
@@ -349,18 +354,57 @@ fn match_poly_trait_ref_against_goal<'tcx>(
349354 let nested_goals = obligations. into_iter ( ) . map ( |o| o. into ( ) ) . collect ( ) ;
350355
351356 let Ok ( certainty) = acx. cx . evaluate_all ( acx. infcx , nested_goals) else { return } ;
352- acx. try_insert_candidate ( candidate ( ) , certainty) ;
357+ acx. try_insert_candidate ( candidate, certainty) ;
353358 } )
354359}
355360
361+ // Evaluate the goal with a new set of self types, combined with a certainty.
362+ fn evaluate_goal_for_components < ' tcx > (
363+ acx : & mut AssemblyCtxt < ' _ , ' tcx , TraitPredicate < ' tcx > > ,
364+ goal : Goal < ' tcx , TraitPredicate < ' tcx > > ,
365+ components : ComponentsAndCertainty < ' tcx > ,
366+ candidate : CandidateSource ,
367+ ) {
368+ let components = match components {
369+ ComponentsAndCertainty :: Yes ( components) => components,
370+ ComponentsAndCertainty :: Maybe => {
371+ acx. try_insert_candidate ( candidate, Certainty :: Maybe ( MaybeCause :: Ambiguity ) ) ;
372+ return ;
373+ }
374+ ComponentsAndCertainty :: No => {
375+ return ;
376+ }
377+ } ;
378+
379+ let nested_goals = components
380+ . into_iter ( )
381+ . map ( |ty| {
382+ Goal :: new (
383+ acx. cx . tcx ,
384+ goal. param_env ,
385+ ty:: Binder :: dummy ( goal. predicate . with_self_ty ( acx. cx . tcx , ty) ) ,
386+ )
387+ } )
388+ . collect ( ) ;
389+
390+ let Ok ( certainty) = acx. cx . evaluate_all ( acx. infcx , nested_goals) else { return } ;
391+ acx. try_insert_candidate ( candidate, certainty) ;
392+ }
393+
394+ enum ComponentsAndCertainty < ' tcx > {
395+ Yes ( Vec < Ty < ' tcx > > ) ,
396+ Maybe ,
397+ No ,
398+ }
399+
356400// Calculates the constituent types of a type for `auto trait` purposes.
357401//
358402// For types with an "existential" binder, i.e. generator witnesses, we also
359403// instantiate the binder with placeholders eagerly.
360404fn instantiate_constituent_tys_for_auto_trait < ' tcx > (
361405 infcx : & InferCtxt < ' tcx > ,
362406 ty : Ty < ' tcx > ,
363- ) -> Result < Vec < Ty < ' tcx > > , ( ) > {
407+ ) -> ComponentsAndCertainty < ' tcx > {
364408 let tcx = infcx. tcx ;
365409 match * ty. kind ( ) {
366410 ty:: Uint ( _)
@@ -373,53 +417,179 @@ fn instantiate_constituent_tys_for_auto_trait<'tcx>(
373417 | ty:: Error ( _)
374418 | ty:: Infer ( ty:: IntVar ( _) | ty:: FloatVar ( _) )
375419 | ty:: Never
376- | ty:: Char => Ok ( vec ! [ ] ) ,
420+ | ty:: Char => ComponentsAndCertainty :: Yes ( vec ! [ ] ) ,
377421
378422 ty:: Placeholder ( ..)
379423 | ty:: Dynamic ( ..)
380424 | ty:: Param ( ..)
381425 | ty:: Foreign ( ..)
382426 | ty:: Alias ( ty:: Projection , ..)
383- | ty:: Bound ( ..)
384- | ty:: Infer ( ty:: TyVar ( _) ) => {
385- // FIXME: Do we need to mark anything as ambiguous here? Yeah?
386- Err ( ( ) )
387- }
427+ | ty:: Bound ( ..) => ComponentsAndCertainty :: No ,
428+
429+ ty:: Infer ( ty:: TyVar ( _) ) => ComponentsAndCertainty :: Maybe ,
388430
389431 ty:: Infer ( ty:: FreshTy ( _) | ty:: FreshIntTy ( _) | ty:: FreshFloatTy ( _) ) => bug ! ( ) ,
390432
391433 ty:: RawPtr ( ty:: TypeAndMut { ty : element_ty, .. } ) | ty:: Ref ( _, element_ty, _) => {
392- Ok ( vec ! [ element_ty] )
434+ ComponentsAndCertainty :: Yes ( vec ! [ element_ty] )
393435 }
394436
395- ty:: Array ( element_ty, _) | ty:: Slice ( element_ty) => Ok ( vec ! [ element_ty] ) ,
437+ ty:: Array ( element_ty, _) | ty:: Slice ( element_ty) => {
438+ ComponentsAndCertainty :: Yes ( vec ! [ element_ty] )
439+ }
396440
397441 ty:: Tuple ( ref tys) => {
398442 // (T1, ..., Tn) -- meets any bound that all of T1...Tn meet
399- Ok ( tys. iter ( ) . collect ( ) )
443+ ComponentsAndCertainty :: Yes ( tys. iter ( ) . collect ( ) )
400444 }
401445
402- ty:: Closure ( _, ref substs) => Ok ( vec ! [ substs. as_closure( ) . tupled_upvars_ty( ) ] ) ,
446+ ty:: Closure ( _, ref substs) => {
447+ ComponentsAndCertainty :: Yes ( vec ! [ substs. as_closure( ) . tupled_upvars_ty( ) ] )
448+ }
403449
404450 ty:: Generator ( _, ref substs, _) => {
405451 let generator_substs = substs. as_generator ( ) ;
406- Ok ( vec ! [ generator_substs. tupled_upvars_ty( ) , generator_substs. witness( ) ] )
452+ ComponentsAndCertainty :: Yes ( vec ! [
453+ generator_substs. tupled_upvars_ty( ) ,
454+ generator_substs. witness( ) ,
455+ ] )
407456 }
408457
409458 ty:: GeneratorWitness ( types) => {
410- Ok ( infcx. replace_bound_vars_with_placeholders ( types) . to_vec ( ) )
459+ ComponentsAndCertainty :: Yes ( infcx. replace_bound_vars_with_placeholders ( types) . to_vec ( ) )
411460 }
412461
413462 // For `PhantomData<T>`, we pass `T`.
414- ty:: Adt ( def, substs) if def. is_phantom_data ( ) => Ok ( vec ! [ substs. type_at( 0 ) ] ) ,
463+ ty:: Adt ( def, substs) if def. is_phantom_data ( ) => {
464+ ComponentsAndCertainty :: Yes ( vec ! [ substs. type_at( 0 ) ] )
465+ }
415466
416- ty:: Adt ( def, substs) => Ok ( def. all_fields ( ) . map ( |f| f. ty ( tcx, substs) ) . collect ( ) ) ,
467+ ty:: Adt ( def, substs) => {
468+ ComponentsAndCertainty :: Yes ( def. all_fields ( ) . map ( |f| f. ty ( tcx, substs) ) . collect ( ) )
469+ }
417470
418471 ty:: Alias ( ty:: Opaque , ty:: AliasTy { def_id, substs, .. } ) => {
419472 // We can resolve the `impl Trait` to its concrete type,
420473 // which enforces a DAG between the functions requiring
421474 // the auto trait bounds in question.
422- Ok ( vec ! [ tcx. bound_type_of( def_id) . subst( tcx, substs) ] )
475+ ComponentsAndCertainty :: Yes ( vec ! [ tcx. bound_type_of( def_id) . subst( tcx, substs) ] )
476+ }
477+ }
478+ }
479+
480+ fn instantiate_constituent_tys_for_sized_trait < ' tcx > (
481+ infcx : & InferCtxt < ' tcx > ,
482+ ty : Ty < ' tcx > ,
483+ ) -> ComponentsAndCertainty < ' tcx > {
484+ match * ty. kind ( ) {
485+ ty:: Infer ( ty:: IntVar ( _) | ty:: FloatVar ( _) )
486+ | ty:: Uint ( _)
487+ | ty:: Int ( _)
488+ | ty:: Bool
489+ | ty:: Float ( _)
490+ | ty:: FnDef ( ..)
491+ | ty:: FnPtr ( _)
492+ | ty:: RawPtr ( ..)
493+ | ty:: Char
494+ | ty:: Ref ( ..)
495+ | ty:: Generator ( ..)
496+ | ty:: GeneratorWitness ( ..)
497+ | ty:: Array ( ..)
498+ | ty:: Closure ( ..)
499+ | ty:: Never
500+ | ty:: Dynamic ( _, _, ty:: DynStar )
501+ | ty:: Error ( _) => ComponentsAndCertainty :: Yes ( vec ! [ ] ) ,
502+
503+ ty:: Str
504+ | ty:: Slice ( _)
505+ | ty:: Dynamic ( ..)
506+ | ty:: Foreign ( ..)
507+ | ty:: Alias ( ..)
508+ | ty:: Param ( _) => ComponentsAndCertainty :: No ,
509+
510+ ty:: Infer ( ty:: TyVar ( _) ) => ComponentsAndCertainty :: Maybe ,
511+
512+ ty:: Placeholder ( ..)
513+ | ty:: Bound ( ..)
514+ | ty:: Infer ( ty:: FreshTy ( _) | ty:: FreshIntTy ( _) | ty:: FreshFloatTy ( _) ) => bug ! ( ) ,
515+
516+ ty:: Tuple ( tys) => ComponentsAndCertainty :: Yes ( tys. to_vec ( ) ) ,
517+
518+ ty:: Adt ( def, substs) => {
519+ let sized_crit = def. sized_constraint ( infcx. tcx ) ;
520+ ComponentsAndCertainty :: Yes (
521+ sized_crit
522+ . 0
523+ . iter ( )
524+ . map ( |ty| sized_crit. rebind ( * ty) . subst ( infcx. tcx , substs) )
525+ . collect ( ) ,
526+ )
527+ }
528+ }
529+ }
530+
531+ fn instantiate_constituent_tys_for_copy_clone_trait < ' tcx > (
532+ infcx : & InferCtxt < ' tcx > ,
533+ ty : Ty < ' tcx > ,
534+ ) -> ComponentsAndCertainty < ' tcx > {
535+ match * ty. kind ( ) {
536+ ty:: Infer ( ty:: IntVar ( _) | ty:: FloatVar ( _) )
537+ | ty:: FnDef ( ..)
538+ | ty:: FnPtr ( _)
539+ | ty:: Error ( _) => ComponentsAndCertainty :: Yes ( vec ! [ ] ) ,
540+
541+ // Implementations are provided in core
542+ ty:: Uint ( _)
543+ | ty:: Int ( _)
544+ | ty:: Bool
545+ | ty:: Float ( _)
546+ | ty:: Char
547+ | ty:: RawPtr ( ..)
548+ | ty:: Never
549+ | ty:: Ref ( _, _, Mutability :: Not )
550+ | ty:: Array ( ..) => ComponentsAndCertainty :: No ,
551+
552+ ty:: Dynamic ( ..)
553+ | ty:: Str
554+ | ty:: Slice ( _)
555+ | ty:: Generator ( _, _, Movability :: Static )
556+ | ty:: Foreign ( ..)
557+ | ty:: Ref ( _, _, Mutability :: Mut )
558+ | ty:: Adt ( _, _)
559+ | ty:: Alias ( _, _)
560+ | ty:: Param ( _) => ComponentsAndCertainty :: No ,
561+
562+ ty:: Infer ( ty:: TyVar ( _) ) => ComponentsAndCertainty :: Maybe ,
563+
564+ ty:: Placeholder ( ..)
565+ | ty:: Bound ( ..)
566+ | ty:: Infer ( ty:: FreshTy ( _) | ty:: FreshIntTy ( _) | ty:: FreshFloatTy ( _) ) => bug ! ( ) ,
567+
568+ ty:: Tuple ( tys) => ComponentsAndCertainty :: Yes ( tys. to_vec ( ) ) ,
569+
570+ ty:: Closure ( _, substs) => match * substs. as_closure ( ) . tupled_upvars_ty ( ) . kind ( ) {
571+ ty:: Tuple ( tys) => ComponentsAndCertainty :: Yes ( tys. to_vec ( ) ) ,
572+ ty:: Infer ( ty:: TyVar ( _) ) => ComponentsAndCertainty :: Maybe ,
573+ _ => bug ! ( ) ,
574+ } ,
575+
576+ ty:: Generator ( _, substs, Movability :: Movable ) => {
577+ if infcx. tcx . features ( ) . generator_clone {
578+ let generator = substs. as_generator ( ) ;
579+ match * generator. tupled_upvars_ty ( ) . kind ( ) {
580+ ty:: Tuple ( tys) => ComponentsAndCertainty :: Yes (
581+ tys. iter ( ) . chain ( [ generator. witness ( ) ] ) . collect ( ) ,
582+ ) ,
583+ ty:: Infer ( ty:: TyVar ( _) ) => ComponentsAndCertainty :: Maybe ,
584+ _ => bug ! ( ) ,
585+ }
586+ } else {
587+ ComponentsAndCertainty :: No
588+ }
589+ }
590+
591+ ty:: GeneratorWitness ( types) => {
592+ ComponentsAndCertainty :: Yes ( infcx. replace_bound_vars_with_placeholders ( types) . to_vec ( ) )
423593 }
424594 }
425595}
0 commit comments