@@ -1206,7 +1206,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
12061206 . and_then ( |partial_res| partial_res. full_res ( ) )
12071207 {
12081208 if !res. matches_ns ( Namespace :: TypeNS )
1209- && path. is_potential_trivial_const_arg ( false )
1209+ && path. is_potential_trivial_const_arg ( )
12101210 {
12111211 debug ! (
12121212 "lower_generic_arg: Lowering type argument as const argument: {:?}" ,
@@ -2276,11 +2276,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
22762276 ) -> & ' hir hir:: ConstArg < ' hir > {
22772277 let tcx = self . tcx ;
22782278
2279- let ct_kind = if path
2280- . is_potential_trivial_const_arg ( tcx. features ( ) . min_generic_const_args ( ) )
2281- && ( tcx. features ( ) . min_generic_const_args ( )
2282- || matches ! ( res, Res :: Def ( DefKind :: ConstParam , _) ) )
2283- {
2279+ let is_trivial_path = path. is_potential_trivial_const_arg ( )
2280+ && matches ! ( res, Res :: Def ( DefKind :: ConstParam , _) ) ;
2281+ let ct_kind = if is_trivial_path || tcx. features ( ) . min_generic_const_args ( ) {
22842282 let qpath = self . lower_qpath (
22852283 ty_id,
22862284 & None ,
@@ -2359,6 +2357,81 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
23592357 }
23602358 }
23612359
2360+ #[ instrument( level = "debug" , skip( self ) , ret) ]
2361+ fn lower_expr_to_const_arg_direct ( & mut self , expr : & Expr ) -> hir:: ConstArg < ' hir > {
2362+ let overly_complex_const = |this : & mut Self | {
2363+ let e = this. dcx ( ) . struct_span_err (
2364+ expr. span ,
2365+ "complex const arguments must be placed inside of a `const` block" ,
2366+ ) ;
2367+
2368+ ConstArg { hir_id : this. next_id ( ) , kind : hir:: ConstArgKind :: Error ( expr. span , e. emit ( ) ) }
2369+ } ;
2370+
2371+ match & expr. kind {
2372+ ExprKind :: Path ( qself, path) => {
2373+ let qpath = self . lower_qpath (
2374+ expr. id ,
2375+ qself,
2376+ path,
2377+ ParamMode :: Explicit ,
2378+ AllowReturnTypeNotation :: No ,
2379+ // FIXME(mgca): update for `fn foo() -> Bar<FOO<impl Trait>>` support
2380+ ImplTraitContext :: Disallowed ( ImplTraitPosition :: Path ) ,
2381+ None ,
2382+ ) ;
2383+
2384+ ConstArg { hir_id : self . next_id ( ) , kind : hir:: ConstArgKind :: Path ( qpath) }
2385+ }
2386+ ExprKind :: Struct ( se) => {
2387+ let path = self . lower_qpath (
2388+ expr. id ,
2389+ & se. qself ,
2390+ & se. path ,
2391+ ParamMode :: Explicit ,
2392+ AllowReturnTypeNotation :: No ,
2393+ ImplTraitContext :: Disallowed ( ImplTraitPosition :: Path ) ,
2394+ None ,
2395+ ) ;
2396+
2397+ let fields = self . arena . alloc_from_iter ( se. fields . iter ( ) . map ( |f| {
2398+ let hir_id = self . lower_node_id ( f. id ) ;
2399+ self . lower_attrs ( hir_id, & f. attrs , f. span , Target :: ExprField ) ;
2400+
2401+ let expr = if let ExprKind :: ConstBlock ( anon_const) = & f. expr . kind {
2402+ self . lower_anon_const_to_const_arg_direct ( anon_const)
2403+ } else {
2404+ self . lower_expr_to_const_arg_direct ( & f. expr )
2405+ } ;
2406+
2407+ & * self . arena . alloc ( hir:: ConstArgExprField {
2408+ hir_id,
2409+ field : self . lower_ident ( f. ident ) ,
2410+ expr : self . arena . alloc ( expr) ,
2411+ span : self . lower_span ( f. span ) ,
2412+ } )
2413+ } ) ) ;
2414+
2415+ ConstArg { hir_id : self . next_id ( ) , kind : hir:: ConstArgKind :: Struct ( path, fields) }
2416+ }
2417+ ExprKind :: Underscore => ConstArg {
2418+ hir_id : self . lower_node_id ( expr. id ) ,
2419+ kind : hir:: ConstArgKind :: Infer ( expr. span , ( ) ) ,
2420+ } ,
2421+ ExprKind :: Block ( block, _) => {
2422+ if let [ stmt] = block. stmts . as_slice ( )
2423+ && let StmtKind :: Expr ( expr) = & stmt. kind
2424+ && matches ! ( expr. kind, ExprKind :: Path ( ..) | ExprKind :: Struct ( ..) )
2425+ {
2426+ return self . lower_expr_to_const_arg_direct ( expr) ;
2427+ }
2428+
2429+ overly_complex_const ( self )
2430+ }
2431+ _ => overly_complex_const ( self ) ,
2432+ }
2433+ }
2434+
23622435 /// See [`hir::ConstArg`] for when to use this function vs
23632436 /// [`Self::lower_anon_const_to_anon_const`].
23642437 fn lower_anon_const_to_const_arg ( & mut self , anon : & AnonConst ) -> & ' hir hir:: ConstArg < ' hir > {
@@ -2379,20 +2452,32 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
23792452 } else {
23802453 & anon. value
23812454 } ;
2455+
2456+ if tcx. features ( ) . min_generic_const_args ( ) {
2457+ match anon. mgca_disambiguation {
2458+ MgcaDisambiguation :: AnonConst => {
2459+ let lowered_anon = self . lower_anon_const_to_anon_const ( anon) ;
2460+ return ConstArg {
2461+ hir_id : self . next_id ( ) ,
2462+ kind : hir:: ConstArgKind :: Anon ( lowered_anon) ,
2463+ } ;
2464+ }
2465+ MgcaDisambiguation :: Direct => return self . lower_expr_to_const_arg_direct ( expr) ,
2466+ }
2467+ }
2468+
23822469 let maybe_res =
23832470 self . resolver . get_partial_res ( expr. id ) . and_then ( |partial_res| partial_res. full_res ( ) ) ;
23842471 if let ExprKind :: Path ( qself, path) = & expr. kind
2385- && path. is_potential_trivial_const_arg ( tcx. features ( ) . min_generic_const_args ( ) )
2386- && ( tcx. features ( ) . min_generic_const_args ( )
2387- || matches ! ( maybe_res, Some ( Res :: Def ( DefKind :: ConstParam , _) ) ) )
2472+ && path. is_potential_trivial_const_arg ( )
2473+ && matches ! ( maybe_res, Some ( Res :: Def ( DefKind :: ConstParam , _) ) )
23882474 {
23892475 let qpath = self . lower_qpath (
23902476 expr. id ,
23912477 qself,
23922478 path,
23932479 ParamMode :: Explicit ,
23942480 AllowReturnTypeNotation :: No ,
2395- // FIXME(mgca): update for `fn foo() -> Bar<FOO<impl Trait>>` support
23962481 ImplTraitContext :: Disallowed ( ImplTraitPosition :: Path ) ,
23972482 None ,
23982483 ) ;
0 commit comments