rustc: replace GenericArgs::with_generic_args hack with a plain getter.

This commit is contained in:
Eduard-Mihai Burtescu 2019-06-12 11:42:58 +03:00
parent e79b2a18a2
commit 887feeeaf7
6 changed files with 91 additions and 102 deletions

View File

@ -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<F, R>(&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(),

View File

@ -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)
}
}
}

View File

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

View File

@ -2809,7 +2809,8 @@ impl Clean<Type> 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<Type> 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<PathSegment> 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),
}
}
}

View File

@ -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)]

View File

@ -133,8 +133,15 @@ impl<T: Encodable> Encodable for P<T> {
}
impl<T> 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)]