Skip to content

Commit

Permalink
Auto merge of rust-lang#108145 - matthiaskrgr:rollup-bgadak1, r=matth…
Browse files Browse the repository at this point in the history
…iaskrgr

Rollup of 8 pull requests

Successful merges:

 - rust-lang#104068 (rustdoc: Add PartialOrd trait to doc comment explanation)
 - rust-lang#107489 (Implement partial support for non-lifetime binders)
 - rust-lang#107905 (Pass arguments to `x` subcommands with `--`)
 - rust-lang#108009 (Move some tests)
 - rust-lang#108086 (wasm: Register the `relaxed-simd` target feature)
 - rust-lang#108104 (don't into self)
 - rust-lang#108133 (Small cleanups around `EarlyBinder`)
 - rust-lang#108136 (Do not ICE on unmet trait alias impl bounds)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
  • Loading branch information
bors committed Feb 17, 2023
2 parents 947b696 + ecdb7bc commit ea21839
Show file tree
Hide file tree
Showing 95 changed files with 822 additions and 370 deletions.
34 changes: 0 additions & 34 deletions compiler/rustc_ast_passes/src/ast_validation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -294,27 +294,6 @@ impl<'a> AstValidator<'a> {
}
}

fn check_late_bound_lifetime_defs(&self, params: &[GenericParam]) {
// Check only lifetime parameters are present and that the lifetime
// parameters that are present have no bounds.
let non_lt_param_spans: Vec<_> = params
.iter()
.filter_map(|param| match param.kind {
GenericParamKind::Lifetime { .. } => {
if !param.bounds.is_empty() {
let spans: Vec<_> = param.bounds.iter().map(|b| b.span()).collect();
self.session.emit_err(ForbiddenLifetimeBound { spans });
}
None
}
_ => Some(param.ident.span),
})
.collect();
if !non_lt_param_spans.is_empty() {
self.session.emit_err(ForbiddenNonLifetimeParam { spans: non_lt_param_spans });
}
}

fn check_fn_decl(&self, fn_decl: &FnDecl, self_semantic: SelfSemantic) {
self.check_decl_num_args(fn_decl);
self.check_decl_cvaradic_pos(fn_decl);
Expand Down Expand Up @@ -745,7 +724,6 @@ impl<'a> AstValidator<'a> {
)
.emit();
});
self.check_late_bound_lifetime_defs(&bfty.generic_params);
if let Extern::Implicit(_) = bfty.ext {
let sig_span = self.session.source_map().next_point(ty.span.shrink_to_lo());
self.maybe_lint_missing_abi(sig_span, ty.id);
Expand Down Expand Up @@ -1318,9 +1296,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
for predicate in &generics.where_clause.predicates {
match predicate {
WherePredicate::BoundPredicate(bound_pred) => {
// A type binding, eg `for<'c> Foo: Send+Clone+'c`
self.check_late_bound_lifetime_defs(&bound_pred.bound_generic_params);

// This is slightly complicated. Our representation for poly-trait-refs contains a single
// binder and thus we only allow a single level of quantification. However,
// the syntax of Rust permits quantification in two places in where clauses,
Expand Down Expand Up @@ -1396,11 +1371,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
visit::walk_param_bound(self, bound)
}

fn visit_poly_trait_ref(&mut self, t: &'a PolyTraitRef) {
self.check_late_bound_lifetime_defs(&t.bound_generic_params);
visit::walk_poly_trait_ref(self, t);
}

fn visit_variant_data(&mut self, s: &'a VariantData) {
self.with_banned_assoc_ty_bound(|this| visit::walk_struct_def(this, s))
}
Expand Down Expand Up @@ -1437,10 +1407,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
.emit();
}

if let FnKind::Closure(ClosureBinder::For { generic_params, .. }, ..) = fk {
self.check_late_bound_lifetime_defs(generic_params);
}

if let FnKind::Fn(
_,
_,
Expand Down
55 changes: 54 additions & 1 deletion compiler/rustc_ast_passes/src/feature_gate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ use rustc_span::symbol::sym;
use rustc_span::Span;
use rustc_target::spec::abi;

use crate::errors::ForbiddenLifetimeBound;

macro_rules! gate_feature_fn {
($visitor: expr, $has_feature: expr, $span: expr, $name: expr, $explain: expr, $help: expr) => {{
let (visitor, has_feature, span, name, explain, help) =
Expand Down Expand Up @@ -136,6 +138,34 @@ impl<'a> PostExpansionVisitor<'a> {
}
ImplTraitVisitor { vis: self }.visit_ty(ty);
}

fn check_late_bound_lifetime_defs(&self, params: &[ast::GenericParam]) {
// Check only lifetime parameters are present and that the lifetime
// parameters that are present have no bounds.
let non_lt_param_spans: Vec<_> = params
.iter()
.filter_map(|param| match param.kind {
ast::GenericParamKind::Lifetime { .. } => None,
_ => Some(param.ident.span),
})
.collect();
// FIXME: gate_feature_post doesn't really handle multispans...
if !non_lt_param_spans.is_empty() && !self.features.non_lifetime_binders {
feature_err(
&self.sess.parse_sess,
sym::non_lifetime_binders,
non_lt_param_spans,
rustc_errors::fluent::ast_passes_forbidden_non_lifetime_param,
)
.emit();
}
for param in params {
if !param.bounds.is_empty() {
let spans: Vec<_> = param.bounds.iter().map(|b| b.span()).collect();
self.sess.emit_err(ForbiddenLifetimeBound { spans });
}
}
}
}

impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
Expand All @@ -147,7 +177,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
..
}) = attr_info
{
gate_feature_fn!(self, has_feature, attr.span, *name, descr);
gate_feature_fn!(self, has_feature, attr.span, *name, *descr);
}
// Check unstable flavors of the `#[doc]` attribute.
if attr.has_name(sym::doc) {
Expand Down Expand Up @@ -306,6 +336,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
ast::TyKind::BareFn(bare_fn_ty) => {
// Function pointers cannot be `const`
self.check_extern(bare_fn_ty.ext, ast::Const::No);
self.check_late_bound_lifetime_defs(&bare_fn_ty.generic_params);
}
ast::TyKind::Never => {
gate_feature_post!(&self, never_type, ty.span, "the `!` type is experimental");
Expand All @@ -318,6 +349,19 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
visit::walk_ty(self, ty)
}

fn visit_generics(&mut self, g: &'a ast::Generics) {
for predicate in &g.where_clause.predicates {
match predicate {
ast::WherePredicate::BoundPredicate(bound_pred) => {
// A type binding, eg `for<'c> Foo: Send+Clone+'c`
self.check_late_bound_lifetime_defs(&bound_pred.bound_generic_params);
}
_ => {}
}
}
visit::walk_generics(self, g);
}

fn visit_fn_ret_ty(&mut self, ret_ty: &'a ast::FnRetTy) {
if let ast::FnRetTy::Ty(output_ty) = ret_ty {
if let ast::TyKind::Never = output_ty.kind {
Expand Down Expand Up @@ -437,12 +481,21 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
visit::walk_pat(self, pattern)
}

fn visit_poly_trait_ref(&mut self, t: &'a ast::PolyTraitRef) {
self.check_late_bound_lifetime_defs(&t.bound_generic_params);
visit::walk_poly_trait_ref(self, t);
}

fn visit_fn(&mut self, fn_kind: FnKind<'a>, span: Span, _: NodeId) {
if let Some(header) = fn_kind.header() {
// Stability of const fn methods are covered in `visit_assoc_item` below.
self.check_extern(header.ext, header.constness);
}

if let FnKind::Closure(ast::ClosureBinder::For { generic_params, .. }, ..) = fn_kind {
self.check_late_bound_lifetime_defs(generic_params);
}

if fn_kind.ctxt() != Some(FnCtxt::Foreign) && fn_kind.decl().c_variadic() {
gate_feature_post!(&self, c_variadic, span, "C-variadic functions are unstable");
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_attr/src/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -731,7 +731,7 @@ pub fn eval_condition(
sess,
sym::cfg_target_compact,
cfg.span,
&"compact `cfg(target(..))` is experimental and subject to change"
"compact `cfg(target(..))` is experimental and subject to change"
).emit();
}

Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_codegen_ssa/src/target_features.rs
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,7 @@ const WASM_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
("mutable-globals", Some(sym::wasm_target_feature)),
("nontrapping-fptoint", Some(sym::wasm_target_feature)),
("reference-types", Some(sym::wasm_target_feature)),
("relaxed-simd", Some(sym::wasm_target_feature)),
("sign-ext", Some(sym::wasm_target_feature)),
("simd128", None),
// tidy-alphabetical-end
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_feature/src/active.rs
Original file line number Diff line number Diff line change
Expand Up @@ -473,6 +473,8 @@ declare_features! (
(active, no_sanitize, "1.42.0", Some(39699), None),
/// Allows using the `non_exhaustive_omitted_patterns` lint.
(active, non_exhaustive_omitted_patterns_lint, "1.57.0", Some(89554), None),
/// Allows `for<T>` binders in where-clauses
(incomplete, non_lifetime_binders, "CURRENT_RUSTC_VERSION", Some(1), None),
/// Allows making `dyn Trait` well-formed even if `Trait` is not object safe.
/// In that case, `dyn Trait: Trait` does not hold. Moreover, coercions and
/// casts in safe Rust to `dyn Trait` for such a `Trait` is also forbidden.
Expand Down
91 changes: 75 additions & 16 deletions compiler/rustc_hir_analysis/src/astconv/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use crate::errors::{
AmbiguousLifetimeBound, MultipleRelaxedDefaultBounds, TraitObjectDeclaredWithNoTraits,
TypeofReservedKeywordUsed, ValueOfAssociatedStructAlreadySpecified,
};
use crate::middle::resolve_lifetime as rl;
use crate::middle::resolve_bound_vars as rbv;
use crate::require_c_abi_if_c_variadic;
use rustc_ast::TraitObjectSyntax;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
Expand Down Expand Up @@ -225,10 +225,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
let tcx = self.tcx();
let lifetime_name = |def_id| tcx.hir().name(tcx.hir().local_def_id_to_hir_id(def_id));

match tcx.named_region(lifetime.hir_id) {
Some(rl::Region::Static) => tcx.lifetimes.re_static,
match tcx.named_bound_var(lifetime.hir_id) {
Some(rbv::ResolvedArg::StaticLifetime) => tcx.lifetimes.re_static,

Some(rl::Region::LateBound(debruijn, index, def_id)) => {
Some(rbv::ResolvedArg::LateBound(debruijn, index, def_id)) => {
let name = lifetime_name(def_id.expect_local());
let br = ty::BoundRegion {
var: ty::BoundVar::from_u32(index),
Expand All @@ -237,15 +237,15 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
tcx.mk_re_late_bound(debruijn, br)
}

Some(rl::Region::EarlyBound(def_id)) => {
Some(rbv::ResolvedArg::EarlyBound(def_id)) => {
let name = tcx.hir().ty_param_name(def_id.expect_local());
let item_def_id = tcx.hir().ty_param_owner(def_id.expect_local());
let generics = tcx.generics_of(item_def_id);
let index = generics.param_def_id_to_index[&def_id];
tcx.mk_re_early_bound(ty::EarlyBoundRegion { def_id, index, name })
}

Some(rl::Region::Free(scope, id)) => {
Some(rbv::ResolvedArg::Free(scope, id)) => {
let name = lifetime_name(id.expect_local());
tcx.mk_re_free(scope, ty::BrNamed(id, name))

Expand Down Expand Up @@ -1607,7 +1607,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
self.ast_region_to_region(lifetime, None)
} else {
self.compute_object_lifetime_bound(span, existential_predicates).unwrap_or_else(|| {
if tcx.named_region(lifetime.hir_id).is_some() {
if tcx.named_bound_var(lifetime.hir_id).is_some() {
self.ast_region_to_region(lifetime, None)
} else {
self.re_infer(None, span).unwrap_or_else(|| {
Expand Down Expand Up @@ -2600,6 +2600,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
&self,
opt_self_ty: Option<Ty<'tcx>>,
path: &hir::Path<'_>,
hir_id: hir::HirId,
permit_variants: bool,
) -> Ty<'tcx> {
let tcx = self.tcx();
Expand Down Expand Up @@ -2663,11 +2664,25 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
}
});

let def_id = def_id.expect_local();
let item_def_id = tcx.hir().ty_param_owner(def_id);
let generics = tcx.generics_of(item_def_id);
let index = generics.param_def_id_to_index[&def_id.to_def_id()];
tcx.mk_ty_param(index, tcx.hir().ty_param_name(def_id))
match tcx.named_bound_var(hir_id) {
Some(rbv::ResolvedArg::LateBound(debruijn, index, _)) => {
let name =
tcx.hir().name(tcx.hir().local_def_id_to_hir_id(def_id.expect_local()));
let br = ty::BoundTy {
var: ty::BoundVar::from_u32(index),
kind: ty::BoundTyKind::Param(def_id, name),
};
tcx.mk_ty(ty::Bound(debruijn, br))
}
Some(rbv::ResolvedArg::EarlyBound(_)) => {
let def_id = def_id.expect_local();
let item_def_id = tcx.hir().ty_param_owner(def_id);
let generics = tcx.generics_of(item_def_id);
let index = generics.param_def_id_to_index[&def_id.to_def_id()];
tcx.mk_ty_param(index, tcx.hir().ty_param_name(def_id))
}
arg => bug!("unexpected bound var resolution for {hir_id:?}: {arg:?}"),
}
}
Res::SelfTyParam { .. } => {
// `Self` in trait or type alias.
Expand Down Expand Up @@ -2870,27 +2885,50 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
hir::TyKind::BareFn(bf) => {
require_c_abi_if_c_variadic(tcx, bf.decl, bf.abi, ast_ty.span);

tcx.mk_fn_ptr(self.ty_of_fn(
let fn_ptr_ty = tcx.mk_fn_ptr(self.ty_of_fn(
ast_ty.hir_id,
bf.unsafety,
bf.abi,
bf.decl,
None,
Some(ast_ty),
))
));

if let Some(guar) =
deny_non_region_late_bound(tcx, bf.generic_params, "function pointer")
{
tcx.ty_error_with_guaranteed(guar)
} else {
fn_ptr_ty
}
}
hir::TyKind::TraitObject(bounds, lifetime, repr) => {
self.maybe_lint_bare_trait(ast_ty, in_path);
let repr = match repr {
TraitObjectSyntax::Dyn | TraitObjectSyntax::None => ty::Dyn,
TraitObjectSyntax::DynStar => ty::DynStar,
};
self.conv_object_ty_poly_trait_ref(ast_ty.span, bounds, lifetime, borrowed, repr)

let object_ty = self.conv_object_ty_poly_trait_ref(
ast_ty.span,
bounds,
lifetime,
borrowed,
repr,
);

if let Some(guar) = bounds.iter().find_map(|trait_ref| {
deny_non_region_late_bound(tcx, trait_ref.bound_generic_params, "trait object")
}) {
tcx.ty_error_with_guaranteed(guar)
} else {
object_ty
}
}
hir::TyKind::Path(hir::QPath::Resolved(maybe_qself, path)) => {
debug!(?maybe_qself, ?path);
let opt_self_ty = maybe_qself.as_ref().map(|qself| self.ast_ty_to_ty(qself));
self.res_to_ty(opt_self_ty, path, false)
self.res_to_ty(opt_self_ty, path, ast_ty.hir_id, false)
}
&hir::TyKind::OpaqueDef(item_id, lifetimes, in_trait) => {
let opaque_ty = tcx.hir().item(item_id);
Expand Down Expand Up @@ -3346,3 +3384,24 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
}
}
}

fn deny_non_region_late_bound(
tcx: TyCtxt<'_>,
params: &[hir::GenericParam<'_>],
where_: &str,
) -> Option<ErrorGuaranteed> {
params.iter().find_map(|bad_param| {
let what = match bad_param.kind {
hir::GenericParamKind::Type { .. } => "type",
hir::GenericParamKind::Const { .. } => "const",
hir::GenericParamKind::Lifetime { .. } => return None,
};

let mut diag = tcx.sess.struct_span_err(
bad_param.span,
format!("late-bound {what} parameter not allowed on {where_} types"),
);

Some(if tcx.features().non_lifetime_binders { diag.emit() } else { diag.delay_as_bug() })
})
}
4 changes: 2 additions & 2 deletions compiler/rustc_hir_analysis/src/collect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ use std::iter;

mod generics_of;
mod item_bounds;
mod lifetimes;
mod predicates_of;
mod resolve_bound_vars;
mod type_of;

///////////////////////////////////////////////////////////////////////////
Expand All @@ -53,7 +53,7 @@ fn collect_mod_item_types(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
}

pub fn provide(providers: &mut Providers) {
lifetimes::provide(providers);
resolve_bound_vars::provide(providers);
*providers = Providers {
opt_const_param_of: type_of::opt_const_param_of,
type_of: type_of::type_of,
Expand Down
Loading

0 comments on commit ea21839

Please sign in to comment.