Auto merge of #139622 - matthiaskrgr:rollup-8ri1vid, r=matthiaskrgr
Rollup of 13 pull requests Successful merges: - #138167 (Small code improvement in rustdoc hidden stripper) - #138605 (Clean up librustdoc::html::render to be better encapsulated) - #139423 (Suppress missing field error when autoderef bottoms out in infer) - #139449 (match ergonomics: replace `peel_off_references` with a recursive call) - #139507 (compiletest: Trim whitespace from environment variable names) - #139530 (Remove some dead or leftover code related to rustc-intrinsic abi removal) - #139560 (fix title of offset_of_enum feature) - #139563 (emit a better error message for using the macro incorrectly) - #139568 (Don't use empty trait names) - #139580 (Temporarily leave the review rotation) - #139589 (saethlin is back from vacation) - #139592 (rustdoc: Enable Markdown extensions when looking for doctests) - #139599 (Tracking issue template: fine-grained information on style update status) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
69b3959afe
30 changed files with 269 additions and 330 deletions
|
@ -234,7 +234,7 @@ mod llvm_enzyme {
|
|||
let meta_item_vec: ThinVec<MetaItemInner> = match meta_item.kind {
|
||||
ast::MetaItemKind::List(ref vec) => vec.clone(),
|
||||
_ => {
|
||||
dcx.emit_err(errors::AutoDiffInvalidApplication { span: item.span() });
|
||||
dcx.emit_err(errors::AutoDiffMissingConfig { span: item.span() });
|
||||
return vec![item];
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
#### Note: this error code is no longer emitted by the compiler.
|
||||
|
||||
An intrinsic was declared without being a function.
|
||||
|
||||
Erroneous code example:
|
||||
|
||||
```compile_fail,E0622
|
||||
```no_run
|
||||
#![feature(intrinsics)]
|
||||
#![allow(internal_features)]
|
||||
|
||||
|
|
|
@ -397,7 +397,7 @@ E0618: 0618,
|
|||
E0619: 0619,
|
||||
E0620: 0620,
|
||||
E0621: 0621,
|
||||
E0622: 0622,
|
||||
E0622: 0622, // REMOVED: rustc-intrinsic ABI was removed
|
||||
E0623: 0623,
|
||||
E0624: 0624,
|
||||
E0625: 0625,
|
||||
|
|
|
@ -719,7 +719,6 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) {
|
|||
def_id,
|
||||
tcx.def_ident_span(def_id).unwrap(),
|
||||
i.name,
|
||||
ExternAbi::Rust,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -787,16 +786,6 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) {
|
|||
for item in items {
|
||||
let def_id = item.id.owner_id.def_id;
|
||||
|
||||
if tcx.has_attr(def_id, sym::rustc_intrinsic) {
|
||||
intrinsic::check_intrinsic_type(
|
||||
tcx,
|
||||
item.id.owner_id.def_id,
|
||||
item.span,
|
||||
item.ident.name,
|
||||
abi,
|
||||
);
|
||||
}
|
||||
|
||||
let generics = tcx.generics_of(def_id);
|
||||
let own_counts = generics.own_counts();
|
||||
if generics.own_params.len() - own_counts.lifetimes != 0 {
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
//! Type-checking for the `#[rustc_intrinsic]` intrinsics that the compiler exposes.
|
||||
|
||||
use rustc_abi::ExternAbi;
|
||||
use rustc_errors::codes::*;
|
||||
use rustc_errors::{DiagMessage, struct_span_code_err};
|
||||
use rustc_hir::{self as hir, Safety};
|
||||
use rustc_errors::DiagMessage;
|
||||
use rustc_hir::{self as hir};
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::traits::{ObligationCause, ObligationCauseCode};
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||
|
@ -26,17 +25,10 @@ fn equate_intrinsic_type<'tcx>(
|
|||
sig: ty::PolyFnSig<'tcx>,
|
||||
) {
|
||||
let (generics, span) = match tcx.hir_node_by_def_id(def_id) {
|
||||
hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn { generics, .. }, .. })
|
||||
| hir::Node::ForeignItem(hir::ForeignItem {
|
||||
kind: hir::ForeignItemKind::Fn(_, _, generics),
|
||||
..
|
||||
}) => (tcx.generics_of(def_id), generics.span),
|
||||
_ => {
|
||||
struct_span_code_err!(tcx.dcx(), span, E0622, "intrinsic must be a function")
|
||||
.with_span_label(span, "expected a function")
|
||||
.emit();
|
||||
return;
|
||||
hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn { generics, .. }, .. }) => {
|
||||
(tcx.generics_of(def_id), generics.span)
|
||||
}
|
||||
_ => tcx.dcx().span_bug(span, "intrinsic must be a function"),
|
||||
};
|
||||
let own_counts = generics.own_counts();
|
||||
|
||||
|
@ -70,13 +62,7 @@ fn equate_intrinsic_type<'tcx>(
|
|||
}
|
||||
|
||||
/// Returns the unsafety of the given intrinsic.
|
||||
pub fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) -> hir::Safety {
|
||||
let has_safe_attr = if tcx.has_attr(intrinsic_id, sym::rustc_intrinsic) {
|
||||
tcx.fn_sig(intrinsic_id).skip_binder().safety()
|
||||
} else {
|
||||
// Old-style intrinsics are never safe
|
||||
Safety::Unsafe
|
||||
};
|
||||
fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) -> hir::Safety {
|
||||
let is_in_list = match tcx.item_name(intrinsic_id.into()) {
|
||||
// When adding a new intrinsic to this list,
|
||||
// it's usually worth updating that intrinsic's documentation
|
||||
|
@ -148,7 +134,7 @@ pub fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) -
|
|||
_ => hir::Safety::Unsafe,
|
||||
};
|
||||
|
||||
if has_safe_attr != is_in_list {
|
||||
if tcx.fn_sig(intrinsic_id).skip_binder().safety() != is_in_list {
|
||||
tcx.dcx().struct_span_err(
|
||||
tcx.def_span(intrinsic_id),
|
||||
DiagMessage::from(format!(
|
||||
|
@ -163,12 +149,11 @@ pub fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) -
|
|||
|
||||
/// Remember to add all intrinsics here, in `compiler/rustc_codegen_llvm/src/intrinsic.rs`,
|
||||
/// and in `library/core/src/intrinsics.rs`.
|
||||
pub fn check_intrinsic_type(
|
||||
pub(crate) fn check_intrinsic_type(
|
||||
tcx: TyCtxt<'_>,
|
||||
intrinsic_id: LocalDefId,
|
||||
span: Span,
|
||||
intrinsic_name: Symbol,
|
||||
abi: ExternAbi,
|
||||
) {
|
||||
let generics = tcx.generics_of(intrinsic_id);
|
||||
let param = |n| {
|
||||
|
@ -706,7 +691,7 @@ pub fn check_intrinsic_type(
|
|||
};
|
||||
(n_tps, 0, n_cts, inputs, output, safety)
|
||||
};
|
||||
let sig = tcx.mk_fn_sig(inputs, output, false, safety, abi);
|
||||
let sig = tcx.mk_fn_sig(inputs, output, false, safety, ExternAbi::Rust);
|
||||
let sig = ty::Binder::bind_with_vars(sig, bound_vars);
|
||||
equate_intrinsic_type(tcx, span, intrinsic_id, n_tps, n_lts, n_cts, sig)
|
||||
}
|
||||
|
|
|
@ -2920,8 +2920,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
}
|
||||
// We failed to check the expression, report an error.
|
||||
|
||||
// Emits an error if we deref an infer variable, like calling `.field` on a base type of &_.
|
||||
self.structurally_resolve_type(autoderef.span(), autoderef.final_ty(false));
|
||||
// Emits an error if we deref an infer variable, like calling `.field` on a base type
|
||||
// of `&_`. We can also use this to suppress unnecessary "missing field" errors that
|
||||
// will follow ambiguity errors.
|
||||
let final_ty = self.structurally_resolve_type(autoderef.span(), autoderef.final_ty(false));
|
||||
if let ty::Error(_) = final_ty.kind() {
|
||||
return final_ty;
|
||||
}
|
||||
|
||||
if let Some((adjustments, did)) = private_candidate {
|
||||
// (#90483) apply adjustments to avoid ExprUseVisitor from
|
||||
|
|
|
@ -163,9 +163,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
enum AdjustMode {
|
||||
/// Peel off all immediate reference types.
|
||||
Peel,
|
||||
/// Reset binding mode to the initial mode.
|
||||
/// Used for destructuring assignment, where we don't want any match ergonomics.
|
||||
Reset,
|
||||
/// Pass on the input binding mode and expected type.
|
||||
Pass,
|
||||
}
|
||||
|
@ -321,77 +318,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
/// Conversely, inside this module, `check_pat_top` should never be used.
|
||||
#[instrument(level = "debug", skip(self, pat_info))]
|
||||
fn check_pat(&self, pat: &'tcx Pat<'tcx>, expected: Ty<'tcx>, pat_info: PatInfo<'tcx>) {
|
||||
let PatInfo { binding_mode, max_ref_mutbl, top_info: ti, current_depth, .. } = pat_info;
|
||||
|
||||
let path_res = match pat.kind {
|
||||
let opt_path_res = match pat.kind {
|
||||
PatKind::Expr(PatExpr { kind: PatExprKind::Path(qpath), hir_id, span }) => {
|
||||
Some(self.resolve_ty_and_res_fully_qualified_call(qpath, *hir_id, *span))
|
||||
}
|
||||
_ => None,
|
||||
};
|
||||
let adjust_mode = self.calc_adjust_mode(pat, path_res.map(|(res, ..)| res));
|
||||
let (expected, binding_mode, max_ref_mutbl) =
|
||||
self.calc_default_binding_mode(pat, expected, binding_mode, adjust_mode, max_ref_mutbl);
|
||||
let pat_info = PatInfo {
|
||||
binding_mode,
|
||||
max_ref_mutbl,
|
||||
top_info: ti,
|
||||
decl_origin: pat_info.decl_origin,
|
||||
current_depth: current_depth + 1,
|
||||
};
|
||||
|
||||
let ty = match pat.kind {
|
||||
PatKind::Missing | PatKind::Wild | PatKind::Err(_) => expected,
|
||||
// We allow any type here; we ensure that the type is uninhabited during match checking.
|
||||
PatKind::Never => expected,
|
||||
PatKind::Expr(PatExpr { kind: PatExprKind::Path(qpath), hir_id, span }) => {
|
||||
let ty = self.check_pat_path(
|
||||
*hir_id,
|
||||
pat.hir_id,
|
||||
*span,
|
||||
qpath,
|
||||
path_res.unwrap(),
|
||||
expected,
|
||||
&pat_info.top_info,
|
||||
);
|
||||
self.write_ty(*hir_id, ty);
|
||||
ty
|
||||
}
|
||||
PatKind::Expr(lt) => self.check_pat_lit(pat.span, lt, expected, &pat_info.top_info),
|
||||
PatKind::Range(lhs, rhs, _) => {
|
||||
self.check_pat_range(pat.span, lhs, rhs, expected, &pat_info.top_info)
|
||||
}
|
||||
PatKind::Binding(ba, var_id, ident, sub) => {
|
||||
self.check_pat_ident(pat, ba, var_id, ident, sub, expected, pat_info)
|
||||
}
|
||||
PatKind::TupleStruct(ref qpath, subpats, ddpos) => {
|
||||
self.check_pat_tuple_struct(pat, qpath, subpats, ddpos, expected, pat_info)
|
||||
}
|
||||
PatKind::Struct(ref qpath, fields, has_rest_pat) => {
|
||||
self.check_pat_struct(pat, qpath, fields, has_rest_pat, expected, pat_info)
|
||||
}
|
||||
PatKind::Guard(pat, cond) => {
|
||||
self.check_pat(pat, expected, pat_info);
|
||||
self.check_expr_has_type_or_error(cond, self.tcx.types.bool, |_| {});
|
||||
expected
|
||||
}
|
||||
PatKind::Or(pats) => {
|
||||
for pat in pats {
|
||||
self.check_pat(pat, expected, pat_info);
|
||||
}
|
||||
expected
|
||||
}
|
||||
PatKind::Tuple(elements, ddpos) => {
|
||||
self.check_pat_tuple(pat.span, elements, ddpos, expected, pat_info)
|
||||
}
|
||||
PatKind::Box(inner) => self.check_pat_box(pat.span, inner, expected, pat_info),
|
||||
PatKind::Deref(inner) => self.check_pat_deref(pat.span, inner, expected, pat_info),
|
||||
PatKind::Ref(inner, mutbl) => self.check_pat_ref(pat, inner, mutbl, expected, pat_info),
|
||||
PatKind::Slice(before, slice, after) => {
|
||||
self.check_pat_slice(pat.span, before, slice, after, expected, pat_info)
|
||||
}
|
||||
};
|
||||
|
||||
let adjust_mode = self.calc_adjust_mode(pat, opt_path_res.map(|(res, ..)| res));
|
||||
let ty = self.check_pat_inner(pat, opt_path_res, adjust_mode, expected, pat_info);
|
||||
self.write_ty(pat.hir_id, ty);
|
||||
|
||||
// (note_1): In most of the cases where (note_1) is referenced
|
||||
|
@ -437,27 +371,126 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
// `regions-relate-bound-regions-on-closures-to-inference-variables.rs`,
|
||||
}
|
||||
|
||||
/// Compute the new expected type and default binding mode from the old ones
|
||||
/// as well as the pattern form we are currently checking.
|
||||
fn calc_default_binding_mode(
|
||||
// Helper to avoid resolving the same path pattern several times.
|
||||
fn check_pat_inner(
|
||||
&self,
|
||||
pat: &'tcx Pat<'tcx>,
|
||||
expected: Ty<'tcx>,
|
||||
def_br: ByRef,
|
||||
opt_path_res: Option<(Res, Option<LoweredTy<'tcx>>, &'tcx [hir::PathSegment<'tcx>])>,
|
||||
adjust_mode: AdjustMode,
|
||||
max_ref_mutbl: MutblCap,
|
||||
) -> (Ty<'tcx>, ByRef, MutblCap) {
|
||||
expected: Ty<'tcx>,
|
||||
pat_info: PatInfo<'tcx>,
|
||||
) -> Ty<'tcx> {
|
||||
#[cfg(debug_assertions)]
|
||||
if def_br == ByRef::Yes(Mutability::Mut)
|
||||
&& max_ref_mutbl != MutblCap::Mut
|
||||
if pat_info.binding_mode == ByRef::Yes(Mutability::Mut)
|
||||
&& pat_info.max_ref_mutbl != MutblCap::Mut
|
||||
&& self.downgrade_mut_inside_shared()
|
||||
{
|
||||
span_bug!(pat.span, "Pattern mutability cap violated!");
|
||||
}
|
||||
match adjust_mode {
|
||||
AdjustMode::Pass => (expected, def_br, max_ref_mutbl),
|
||||
AdjustMode::Reset => (expected, ByRef::No, MutblCap::Mut),
|
||||
AdjustMode::Peel => self.peel_off_references(pat, expected, def_br, max_ref_mutbl),
|
||||
|
||||
// Resolve type if needed.
|
||||
let expected = if let AdjustMode::Peel = adjust_mode
|
||||
&& pat.default_binding_modes
|
||||
{
|
||||
self.try_structurally_resolve_type(pat.span, expected)
|
||||
} else {
|
||||
expected
|
||||
};
|
||||
let old_pat_info = pat_info;
|
||||
let pat_info = PatInfo { current_depth: old_pat_info.current_depth + 1, ..old_pat_info };
|
||||
|
||||
match pat.kind {
|
||||
// Peel off a `&` or `&mut` from the scrutinee type. See the examples in
|
||||
// `tests/ui/rfcs/rfc-2005-default-binding-mode`.
|
||||
_ if let AdjustMode::Peel = adjust_mode
|
||||
&& pat.default_binding_modes
|
||||
&& let ty::Ref(_, inner_ty, inner_mutability) = *expected.kind() =>
|
||||
{
|
||||
debug!("inspecting {:?}", expected);
|
||||
|
||||
debug!("current discriminant is Ref, inserting implicit deref");
|
||||
// Preserve the reference type. We'll need it later during THIR lowering.
|
||||
self.typeck_results
|
||||
.borrow_mut()
|
||||
.pat_adjustments_mut()
|
||||
.entry(pat.hir_id)
|
||||
.or_default()
|
||||
.push(expected);
|
||||
|
||||
let mut binding_mode = ByRef::Yes(match pat_info.binding_mode {
|
||||
// If default binding mode is by value, make it `ref` or `ref mut`
|
||||
// (depending on whether we observe `&` or `&mut`).
|
||||
ByRef::No |
|
||||
// When `ref mut`, stay a `ref mut` (on `&mut`) or downgrade to `ref` (on `&`).
|
||||
ByRef::Yes(Mutability::Mut) => inner_mutability,
|
||||
// Once a `ref`, always a `ref`.
|
||||
// This is because a `& &mut` cannot mutate the underlying value.
|
||||
ByRef::Yes(Mutability::Not) => Mutability::Not,
|
||||
});
|
||||
|
||||
let mut max_ref_mutbl = pat_info.max_ref_mutbl;
|
||||
if self.downgrade_mut_inside_shared() {
|
||||
binding_mode = binding_mode.cap_ref_mutability(max_ref_mutbl.as_mutbl());
|
||||
}
|
||||
if binding_mode == ByRef::Yes(Mutability::Not) {
|
||||
max_ref_mutbl = MutblCap::Not;
|
||||
}
|
||||
debug!("default binding mode is now {:?}", binding_mode);
|
||||
|
||||
// Use the old pat info to keep `current_depth` to its old value.
|
||||
let new_pat_info = PatInfo { binding_mode, max_ref_mutbl, ..old_pat_info };
|
||||
// Recurse with the new expected type.
|
||||
self.check_pat_inner(pat, opt_path_res, adjust_mode, inner_ty, new_pat_info)
|
||||
}
|
||||
PatKind::Missing | PatKind::Wild | PatKind::Err(_) => expected,
|
||||
// We allow any type here; we ensure that the type is uninhabited during match checking.
|
||||
PatKind::Never => expected,
|
||||
PatKind::Expr(PatExpr { kind: PatExprKind::Path(qpath), hir_id, span }) => {
|
||||
let ty = self.check_pat_path(
|
||||
*hir_id,
|
||||
pat.hir_id,
|
||||
*span,
|
||||
qpath,
|
||||
opt_path_res.unwrap(),
|
||||
expected,
|
||||
&pat_info.top_info,
|
||||
);
|
||||
self.write_ty(*hir_id, ty);
|
||||
ty
|
||||
}
|
||||
PatKind::Expr(lt) => self.check_pat_lit(pat.span, lt, expected, &pat_info.top_info),
|
||||
PatKind::Range(lhs, rhs, _) => {
|
||||
self.check_pat_range(pat.span, lhs, rhs, expected, &pat_info.top_info)
|
||||
}
|
||||
PatKind::Binding(ba, var_id, ident, sub) => {
|
||||
self.check_pat_ident(pat, ba, var_id, ident, sub, expected, pat_info)
|
||||
}
|
||||
PatKind::TupleStruct(ref qpath, subpats, ddpos) => {
|
||||
self.check_pat_tuple_struct(pat, qpath, subpats, ddpos, expected, pat_info)
|
||||
}
|
||||
PatKind::Struct(ref qpath, fields, has_rest_pat) => {
|
||||
self.check_pat_struct(pat, qpath, fields, has_rest_pat, expected, pat_info)
|
||||
}
|
||||
PatKind::Guard(pat, cond) => {
|
||||
self.check_pat(pat, expected, pat_info);
|
||||
self.check_expr_has_type_or_error(cond, self.tcx.types.bool, |_| {});
|
||||
expected
|
||||
}
|
||||
PatKind::Or(pats) => {
|
||||
for pat in pats {
|
||||
self.check_pat(pat, expected, pat_info);
|
||||
}
|
||||
expected
|
||||
}
|
||||
PatKind::Tuple(elements, ddpos) => {
|
||||
self.check_pat_tuple(pat.span, elements, ddpos, expected, pat_info)
|
||||
}
|
||||
PatKind::Box(inner) => self.check_pat_box(pat.span, inner, expected, pat_info),
|
||||
PatKind::Deref(inner) => self.check_pat_deref(pat.span, inner, expected, pat_info),
|
||||
PatKind::Ref(inner, mutbl) => self.check_pat_ref(pat, inner, mutbl, expected, pat_info),
|
||||
PatKind::Slice(before, slice, after) => {
|
||||
self.check_pat_slice(pat.span, before, slice, after, expected, pat_info)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -465,11 +498,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
///
|
||||
/// When the pattern is a path pattern, `opt_path_res` must be `Some(res)`.
|
||||
fn calc_adjust_mode(&self, pat: &'tcx Pat<'tcx>, opt_path_res: Option<Res>) -> AdjustMode {
|
||||
// When we perform destructuring assignment, we disable default match bindings, which are
|
||||
// unintuitive in this context.
|
||||
if !pat.default_binding_modes {
|
||||
return AdjustMode::Reset;
|
||||
}
|
||||
match &pat.kind {
|
||||
// Type checking these product-like types successfully always require
|
||||
// that the expected type be of those types and not reference types.
|
||||
|
@ -526,64 +554,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Peel off as many immediately nested `& mut?` from the expected type as possible
|
||||
/// and return the new expected type and binding default binding mode.
|
||||
/// The adjustments vector, if non-empty is stored in a table.
|
||||
fn peel_off_references(
|
||||
&self,
|
||||
pat: &'tcx Pat<'tcx>,
|
||||
expected: Ty<'tcx>,
|
||||
mut def_br: ByRef,
|
||||
mut max_ref_mutbl: MutblCap,
|
||||
) -> (Ty<'tcx>, ByRef, MutblCap) {
|
||||
let mut expected = self.try_structurally_resolve_type(pat.span, expected);
|
||||
// Peel off as many `&` or `&mut` from the scrutinee type as possible. For example,
|
||||
// for `match &&&mut Some(5)` the loop runs three times, aborting when it reaches
|
||||
// the `Some(5)` which is not of type Ref.
|
||||
//
|
||||
// For each ampersand peeled off, update the binding mode and push the original
|
||||
// type into the adjustments vector.
|
||||
//
|
||||
// See the examples in `ui/match-defbm*.rs`.
|
||||
let mut pat_adjustments = vec![];
|
||||
while let ty::Ref(_, inner_ty, inner_mutability) = *expected.kind() {
|
||||
debug!("inspecting {:?}", expected);
|
||||
|
||||
debug!("current discriminant is Ref, inserting implicit deref");
|
||||
// Preserve the reference type. We'll need it later during THIR lowering.
|
||||
pat_adjustments.push(expected);
|
||||
|
||||
expected = self.try_structurally_resolve_type(pat.span, inner_ty);
|
||||
def_br = ByRef::Yes(match def_br {
|
||||
// If default binding mode is by value, make it `ref` or `ref mut`
|
||||
// (depending on whether we observe `&` or `&mut`).
|
||||
ByRef::No |
|
||||
// When `ref mut`, stay a `ref mut` (on `&mut`) or downgrade to `ref` (on `&`).
|
||||
ByRef::Yes(Mutability::Mut) => inner_mutability,
|
||||
// Once a `ref`, always a `ref`.
|
||||
// This is because a `& &mut` cannot mutate the underlying value.
|
||||
ByRef::Yes(Mutability::Not) => Mutability::Not,
|
||||
});
|
||||
}
|
||||
|
||||
if self.downgrade_mut_inside_shared() {
|
||||
def_br = def_br.cap_ref_mutability(max_ref_mutbl.as_mutbl());
|
||||
}
|
||||
if def_br == ByRef::Yes(Mutability::Not) {
|
||||
max_ref_mutbl = MutblCap::Not;
|
||||
}
|
||||
|
||||
if !pat_adjustments.is_empty() {
|
||||
debug!("default binding mode is now {:?}", def_br);
|
||||
self.typeck_results
|
||||
.borrow_mut()
|
||||
.pat_adjustments_mut()
|
||||
.insert(pat.hir_id, pat_adjustments);
|
||||
}
|
||||
|
||||
(expected, def_br, max_ref_mutbl)
|
||||
}
|
||||
|
||||
fn check_pat_expr_unadjusted(&self, lt: &'tcx hir::PatExpr<'tcx>) -> Ty<'tcx> {
|
||||
let ty = match <.kind {
|
||||
rustc_hir::PatExprKind::Lit { lit, negated } => {
|
||||
|
|
|
@ -602,21 +602,13 @@ impl<'a> Parser<'a> {
|
|||
let polarity = self.parse_polarity();
|
||||
|
||||
// Parse both types and traits as a type, then reinterpret if necessary.
|
||||
let err_path = |span| ast::Path::from_ident(Ident::new(kw::Empty, span));
|
||||
let ty_first = if self.token.is_keyword(kw::For) && self.look_ahead(1, |t| t != &token::Lt)
|
||||
{
|
||||
let span = self.prev_token.span.between(self.token.span);
|
||||
self.dcx().emit_err(errors::MissingTraitInTraitImpl {
|
||||
return Err(self.dcx().create_err(errors::MissingTraitInTraitImpl {
|
||||
span,
|
||||
for_span: span.to(self.token.span),
|
||||
});
|
||||
|
||||
P(Ty {
|
||||
kind: TyKind::Path(None, err_path(span)),
|
||||
span,
|
||||
id: DUMMY_NODE_ID,
|
||||
tokens: None,
|
||||
})
|
||||
}));
|
||||
} else {
|
||||
self.parse_ty_with_generics_recovery(&generics)?
|
||||
};
|
||||
|
@ -657,6 +649,7 @@ impl<'a> Parser<'a> {
|
|||
other => {
|
||||
if let TyKind::ImplTrait(_, bounds) = other
|
||||
&& let [bound] = bounds.as_slice()
|
||||
&& let GenericBound::Trait(poly_trait_ref) = bound
|
||||
{
|
||||
// Suggest removing extra `impl` keyword:
|
||||
// `impl<T: Default> impl Default for Wrapper<T>`
|
||||
|
@ -666,12 +659,12 @@ impl<'a> Parser<'a> {
|
|||
extra_impl_kw,
|
||||
impl_trait_span: ty_first.span,
|
||||
});
|
||||
poly_trait_ref.trait_ref.path.clone()
|
||||
} else {
|
||||
self.dcx().emit_err(errors::ExpectedTraitInTraitImplFoundType {
|
||||
span: ty_first.span,
|
||||
});
|
||||
return Err(self.dcx().create_err(
|
||||
errors::ExpectedTraitInTraitImplFoundType { span: ty_first.span },
|
||||
));
|
||||
}
|
||||
err_path(ty_first.span)
|
||||
}
|
||||
};
|
||||
let trait_ref = TraitRef { path, ref_id: ty_first.id };
|
||||
|
|
|
@ -296,9 +296,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
) -> Option<LexicalScopeBinding<'ra>> {
|
||||
assert!(ns == TypeNS || ns == ValueNS);
|
||||
let orig_ident = ident;
|
||||
if ident.name == kw::Empty {
|
||||
return Some(LexicalScopeBinding::Res(Res::Err));
|
||||
}
|
||||
let (general_span, normalized_span) = if ident.name == kw::SelfUpper {
|
||||
// FIXME(jseyfried) improve `Self` hygiene
|
||||
let empty_span = ident.span.with_ctxt(SyntaxContext::root());
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue