diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 527f18f57dc..de8c75345fe 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -383,17 +383,13 @@ impl PathSegment { } } - // FIXME: hack required because you can't create a static - // `GenericArgs`, so you can't just return a `&GenericArgs`. - pub fn with_generic_args(&self, f: F) -> R - where F: FnOnce(&GenericArgs) -> R - { - let dummy = GenericArgs::none(); - f(if let Some(ref args) = self.args { - &args + pub fn generic_args(&self) -> &GenericArgs { + if let Some(ref args) = self.args { + args } else { - &dummy - }) + const DUMMY: &GenericArgs = &GenericArgs::none(); + DUMMY + } } } @@ -449,7 +445,7 @@ pub struct GenericArgs { } impl GenericArgs { - pub fn none() -> Self { + pub const fn none() -> Self { Self { args: HirVec::new(), bindings: HirVec::new(), diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs index e1c713b537c..8111ac44a87 100644 --- a/src/librustc/hir/print.rs +++ b/src/librustc/hir/print.rs @@ -1194,12 +1194,11 @@ impl<'a> State<'a> { self.s.word(".")?; self.print_ident(segment.ident)?; - segment.with_generic_args(|generic_args| { - if !generic_args.args.is_empty() || !generic_args.bindings.is_empty() { - return self.print_generic_args(&generic_args, segment.infer_args, true); - } - Ok(()) - })?; + let generic_args = segment.generic_args(); + if !generic_args.args.is_empty() || !generic_args.bindings.is_empty() { + self.print_generic_args(generic_args, segment.infer_args, true)?; + } + self.print_call_post(base_args) } @@ -1559,11 +1558,9 @@ impl<'a> State<'a> { self.s.word("::")? } if segment.ident.name != kw::PathRoot { - self.print_ident(segment.ident)?; - segment.with_generic_args(|generic_args| { - self.print_generic_args(generic_args, segment.infer_args, - colons_before_params) - })?; + self.print_ident(segment.ident)?; + self.print_generic_args(segment.generic_args(), segment.infer_args, + colons_before_params)?; } } @@ -1572,10 +1569,8 @@ impl<'a> State<'a> { pub fn print_path_segment(&mut self, segment: &hir::PathSegment) -> io::Result<()> { if segment.ident.name != kw::PathRoot { - self.print_ident(segment.ident)?; - segment.with_generic_args(|generic_args| { - self.print_generic_args(generic_args, segment.infer_args, false) - })?; + self.print_ident(segment.ident)?; + self.print_generic_args(segment.generic_args(), segment.infer_args, false)?; } Ok(()) } @@ -1600,11 +1595,9 @@ impl<'a> State<'a> { } if segment.ident.name != kw::PathRoot { self.print_ident(segment.ident)?; - segment.with_generic_args(|generic_args| { - self.print_generic_args(generic_args, - segment.infer_args, - colons_before_params) - })?; + self.print_generic_args(segment.generic_args(), + segment.infer_args, + colons_before_params)?; } } @@ -1612,11 +1605,9 @@ impl<'a> State<'a> { self.s.word("::")?; let item_segment = path.segments.last().unwrap(); self.print_ident(item_segment.ident)?; - item_segment.with_generic_args(|generic_args| { - self.print_generic_args(generic_args, - item_segment.infer_args, - colons_before_params) - }) + self.print_generic_args(item_segment.generic_args(), + item_segment.infer_args, + colons_before_params) } hir::QPath::TypeRelative(ref qself, ref item_segment) => { self.s.word("<")?; @@ -1624,11 +1615,9 @@ impl<'a> State<'a> { self.s.word(">")?; self.s.word("::")?; self.print_ident(item_segment.ident)?; - item_segment.with_generic_args(|generic_args| { - self.print_generic_args(generic_args, - item_segment.infer_args, - colons_before_params) - }) + self.print_generic_args(item_segment.generic_args(), + item_segment.infer_args, + colons_before_params) } } } diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 8236cd1f738..b6d123c72ac 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -191,15 +191,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { item_segment: &hir::PathSegment) -> SubstsRef<'tcx> { - let (substs, assoc_bindings, _) = item_segment.with_generic_args(|generic_args| { - self.create_substs_for_ast_path( - span, - def_id, - generic_args, - item_segment.infer_args, - None, - ) - }); + let (substs, assoc_bindings, _) = self.create_substs_for_ast_path( + span, + def_id, + item_segment.generic_args(), + item_segment.infer_args, + None, + ); assoc_bindings.first().map(|b| Self::prohibit_assoc_ty_binding(self.tcx(), b.span)); @@ -874,8 +872,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let trait_def = self.tcx().trait_def(trait_def_id); if !self.tcx().features().unboxed_closures && - trait_segment.with_generic_args(|generic_args| generic_args.parenthesized) - != trait_def.paren_sugar { + trait_segment.generic_args().parenthesized != trait_def.paren_sugar + { // For now, require that parenthetical notation be used only with `Fn()` etc. let msg = if trait_def.paren_sugar { "the precise format of `Fn`-family traits' type parameters is subject to change. \ @@ -887,13 +885,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { span, GateIssue::Language, msg); } - trait_segment.with_generic_args(|generic_args| { - self.create_substs_for_ast_path(span, - trait_def_id, - generic_args, - trait_segment.infer_args, - Some(self_ty)) - }) + self.create_substs_for_ast_path(span, + trait_def_id, + trait_segment.generic_args(), + trait_segment.infer_args, + Some(self_ty)) } fn trait_defines_associated_type_named(&self, @@ -1765,47 +1761,45 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { &self, segments: T) -> bool { let mut has_err = false; for segment in segments { - segment.with_generic_args(|generic_args| { - let (mut err_for_lt, mut err_for_ty, mut err_for_ct) = (false, false, false); - for arg in &generic_args.args { - let (span, kind) = match arg { - hir::GenericArg::Lifetime(lt) => { - if err_for_lt { continue } - err_for_lt = true; - has_err = true; - (lt.span, "lifetime") - } - hir::GenericArg::Type(ty) => { - if err_for_ty { continue } - err_for_ty = true; - has_err = true; - (ty.span, "type") - } - hir::GenericArg::Const(ct) => { - if err_for_ct { continue } - err_for_ct = true; - (ct.span, "const") - } - }; - let mut err = struct_span_err!( - self.tcx().sess, - span, - E0109, - "{} arguments are not allowed for this type", - kind, - ); - err.span_label(span, format!("{} argument not allowed", kind)); - err.emit(); - if err_for_lt && err_for_ty && err_for_ct { - break; + let (mut err_for_lt, mut err_for_ty, mut err_for_ct) = (false, false, false); + for arg in &segment.generic_args().args { + let (span, kind) = match arg { + hir::GenericArg::Lifetime(lt) => { + if err_for_lt { continue } + err_for_lt = true; + has_err = true; + (lt.span, "lifetime") } - } - for binding in &generic_args.bindings { - has_err = true; - Self::prohibit_assoc_ty_binding(self.tcx(), binding.span); + hir::GenericArg::Type(ty) => { + if err_for_ty { continue } + err_for_ty = true; + has_err = true; + (ty.span, "type") + } + hir::GenericArg::Const(ct) => { + if err_for_ct { continue } + err_for_ct = true; + (ct.span, "const") + } + }; + let mut err = struct_span_err!( + self.tcx().sess, + span, + E0109, + "{} arguments are not allowed for this type", + kind, + ); + err.span_label(span, format!("{} argument not allowed", kind)); + err.emit(); + if err_for_lt && err_for_ty && err_for_ct { break; } - }) + } + for binding in &segment.generic_args().bindings { + has_err = true; + Self::prohibit_assoc_ty_binding(self.tcx(), binding.span); + break; + } } has_err } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 4becb42d305..9968118d2ec 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2809,7 +2809,8 @@ impl Clean for hir::Ty { let mut ty_substs = FxHashMap::default(); let mut lt_substs = FxHashMap::default(); let mut ct_substs = FxHashMap::default(); - provided_params.with_generic_args(|generic_args| { + let generic_args = provided_params.generic_args(); + { let mut indices: GenericParamCount = Default::default(); for param in generics.params.iter() { match param.kind { @@ -2884,7 +2885,7 @@ impl Clean for hir::Ty { } } } - }); + } return cx.enter_alias(ty_substs, lt_substs, ct_substs, || ty.clean(cx)); } resolve_type(cx, path.clean(cx), self.hir_id) @@ -3537,7 +3538,7 @@ impl Clean for hir::PathSegment { fn clean(&self, cx: &DocContext<'_>) -> PathSegment { PathSegment { name: self.ident.name.clean(cx), - args: self.with_generic_args(|generic_args| generic_args.clean(cx)) + args: self.generic_args().clean(cx), } } } diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs index 55db8da3276..337b8424736 100644 --- a/src/libsyntax/lib.rs +++ b/src/libsyntax/lib.rs @@ -12,6 +12,8 @@ #![deny(unused_lifetimes)] #![feature(bind_by_move_pattern_guards)] +#![feature(const_fn)] +#![feature(const_transmute)] #![feature(crate_visibility_modifier)] #![feature(label_break_value)] #![feature(nll)] diff --git a/src/libsyntax/ptr.rs b/src/libsyntax/ptr.rs index d577243fb3d..f0cfa5a84a8 100644 --- a/src/libsyntax/ptr.rs +++ b/src/libsyntax/ptr.rs @@ -133,8 +133,15 @@ impl Encodable for P { } impl P<[T]> { - pub fn new() -> P<[T]> { - P { ptr: Default::default() } + pub const fn new() -> P<[T]> { + // HACK(eddyb) bypass the lack of a `const fn` to create an empty `Box<[T]>` + // (as trait methods, `default` in this case, can't be `const fn` yet). + P { + ptr: unsafe { + use std::ptr::NonNull; + std::mem::transmute(NonNull::<[T; 0]>::dangling() as NonNull<[T]>) + }, + } } #[inline(never)]