Auto merge of #57580 - Centril:rollup, r=Centril
Rollup of 4 pull requests Successful merges: - #56874 (Simplify foreign type rendering.) - #57113 (Move diagnostics out from QueryJob and optimize for the case with no diagnostics) - #57366 (Point at match discriminant on type error in match arm pattern) - #57538 (librustc_mir: Fix ICE with slice patterns) Failed merges: - #57381 (Tweak output of type mismatch between "then" and `else` `if` arms) r? @ghost
This commit is contained in:
commit
9aee7ed335
50 changed files with 420 additions and 221 deletions
|
|
@ -696,7 +696,7 @@ impl DepGraph {
|
|||
|
||||
// Promote the previous diagnostics to the current session.
|
||||
tcx.queries.on_disk_cache
|
||||
.store_diagnostics(dep_node_index, diagnostics.clone());
|
||||
.store_diagnostics(dep_node_index, diagnostics.clone().into());
|
||||
|
||||
for diagnostic in diagnostics {
|
||||
DiagnosticBuilder::new_diagnostic(handle, diagnostic).emit();
|
||||
|
|
|
|||
|
|
@ -487,6 +487,11 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
|||
|
||||
fn note_error_origin(&self, err: &mut DiagnosticBuilder<'tcx>, cause: &ObligationCause<'tcx>) {
|
||||
match cause.code {
|
||||
ObligationCauseCode::MatchExpressionArmPattern { span, ty } => {
|
||||
if ty.is_suggestable() { // don't show type `_`
|
||||
err.span_label(span, format!("this match expression has type `{}`", ty));
|
||||
}
|
||||
}
|
||||
ObligationCauseCode::MatchExpressionArm { arm_span, source } => match source {
|
||||
hir::MatchSource::IfLetDesugar { .. } => {
|
||||
let msg = "`if let` arm with an incompatible type";
|
||||
|
|
|
|||
|
|
@ -1444,6 +1444,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
|||
match *cause_code {
|
||||
ObligationCauseCode::ExprAssignable |
|
||||
ObligationCauseCode::MatchExpressionArm { .. } |
|
||||
ObligationCauseCode::MatchExpressionArmPattern { .. } |
|
||||
ObligationCauseCode::IfExpression |
|
||||
ObligationCauseCode::IfExpressionWithNoElse |
|
||||
ObligationCauseCode::MainFunctionType |
|
||||
|
|
@ -1451,8 +1452,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
|||
ObligationCauseCode::IntrinsicType |
|
||||
ObligationCauseCode::MethodReceiver |
|
||||
ObligationCauseCode::ReturnNoExpression |
|
||||
ObligationCauseCode::MiscObligation => {
|
||||
}
|
||||
ObligationCauseCode::MiscObligation => {}
|
||||
ObligationCauseCode::SliceOrArrayElem => {
|
||||
err.note("slice and array elements must have `Sized` type");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -220,8 +220,13 @@ pub enum ObligationCauseCode<'tcx> {
|
|||
ExprAssignable,
|
||||
|
||||
/// Computing common supertype in the arms of a match expression
|
||||
MatchExpressionArm { arm_span: Span,
|
||||
source: hir::MatchSource },
|
||||
MatchExpressionArm {
|
||||
arm_span: Span,
|
||||
source: hir::MatchSource,
|
||||
},
|
||||
|
||||
/// Computing common supertype in the pattern guard for the arms of a match expression
|
||||
MatchExpressionArmPattern { span: Span, ty: Ty<'tcx> },
|
||||
|
||||
/// Computing common supertype in an if expression
|
||||
IfExpression,
|
||||
|
|
|
|||
|
|
@ -517,6 +517,9 @@ impl<'a, 'tcx> Lift<'tcx> for traits::ObligationCauseCode<'a> {
|
|||
arm_span,
|
||||
source: source,
|
||||
}),
|
||||
super::MatchExpressionArmPattern { span, ty } => {
|
||||
tcx.lift(&ty).map(|ty| super::MatchExpressionArmPattern { span, ty })
|
||||
}
|
||||
super::IfExpression => Some(super::IfExpression),
|
||||
super::IfExpressionWithNoElse => Some(super::IfExpressionWithNoElse),
|
||||
super::MainFunctionType => Some(super::MainFunctionType),
|
||||
|
|
|
|||
|
|
@ -1682,6 +1682,7 @@ impl<'gcx> GlobalCtxt<'gcx> {
|
|||
let new_icx = ty::tls::ImplicitCtxt {
|
||||
tcx,
|
||||
query: icx.query.clone(),
|
||||
diagnostics: icx.diagnostics,
|
||||
layout_depth: icx.layout_depth,
|
||||
task_deps: icx.task_deps,
|
||||
};
|
||||
|
|
@ -1792,6 +1793,7 @@ pub mod tls {
|
|||
use errors::{Diagnostic, TRACK_DIAGNOSTICS};
|
||||
use rustc_data_structures::OnDrop;
|
||||
use rustc_data_structures::sync::{self, Lrc, Lock};
|
||||
use rustc_data_structures::thin_vec::ThinVec;
|
||||
use dep_graph::TaskDeps;
|
||||
|
||||
#[cfg(not(parallel_queries))]
|
||||
|
|
@ -1811,10 +1813,14 @@ pub mod tls {
|
|||
/// by `enter_local` with a new local interner
|
||||
pub tcx: TyCtxt<'tcx, 'gcx, 'tcx>,
|
||||
|
||||
/// The current query job, if any. This is updated by start_job in
|
||||
/// The current query job, if any. This is updated by JobOwner::start in
|
||||
/// ty::query::plumbing when executing a query
|
||||
pub query: Option<Lrc<query::QueryJob<'gcx>>>,
|
||||
|
||||
/// Where to store diagnostics for the current query job, if any.
|
||||
/// This is updated by JobOwner::start in ty::query::plumbing when executing a query
|
||||
pub diagnostics: Option<&'a Lock<ThinVec<Diagnostic>>>,
|
||||
|
||||
/// Used to prevent layout from recursing too deeply.
|
||||
pub layout_depth: usize,
|
||||
|
||||
|
|
@ -1880,8 +1886,9 @@ pub mod tls {
|
|||
fn track_diagnostic(diagnostic: &Diagnostic) {
|
||||
with_context_opt(|icx| {
|
||||
if let Some(icx) = icx {
|
||||
if let Some(ref query) = icx.query {
|
||||
query.diagnostics.lock().push(diagnostic.clone());
|
||||
if let Some(ref diagnostics) = icx.diagnostics {
|
||||
let mut diagnostics = diagnostics.lock();
|
||||
diagnostics.extend(Some(diagnostic.clone()));
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
@ -1948,6 +1955,7 @@ pub mod tls {
|
|||
let icx = ImplicitCtxt {
|
||||
tcx,
|
||||
query: None,
|
||||
diagnostics: None,
|
||||
layout_depth: 0,
|
||||
task_deps: None,
|
||||
};
|
||||
|
|
@ -1977,6 +1985,7 @@ pub mod tls {
|
|||
};
|
||||
let icx = ImplicitCtxt {
|
||||
query: None,
|
||||
diagnostics: None,
|
||||
tcx,
|
||||
layout_depth: 0,
|
||||
task_deps: None,
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@ use ty::query::{
|
|||
config::QueryDescription,
|
||||
};
|
||||
use ty::context::TyCtxt;
|
||||
use errors::Diagnostic;
|
||||
use std::process;
|
||||
use std::{fmt, ptr};
|
||||
|
||||
|
|
@ -54,9 +53,6 @@ pub struct QueryJob<'tcx> {
|
|||
/// The parent query job which created this job and is implicitly waiting on it.
|
||||
pub parent: Option<Lrc<QueryJob<'tcx>>>,
|
||||
|
||||
/// Diagnostic messages which are emitted while the query executes
|
||||
pub diagnostics: Lock<Vec<Diagnostic>>,
|
||||
|
||||
/// The latch which is used to wait on this job
|
||||
#[cfg(parallel_queries)]
|
||||
latch: QueryLatch<'tcx>,
|
||||
|
|
@ -66,7 +62,6 @@ impl<'tcx> QueryJob<'tcx> {
|
|||
/// Creates a new query job
|
||||
pub fn new(info: QueryInfo<'tcx>, parent: Option<Lrc<QueryJob<'tcx>>>) -> Self {
|
||||
QueryJob {
|
||||
diagnostics: Lock::new(Vec::new()),
|
||||
info,
|
||||
parent,
|
||||
#[cfg(parallel_queries)]
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ use ich::{CachingSourceMapView, Fingerprint};
|
|||
use mir::{self, interpret};
|
||||
use mir::interpret::{AllocDecodingSession, AllocDecodingState};
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_data_structures::thin_vec::ThinVec;
|
||||
use rustc_data_structures::sync::{Lrc, Lock, HashMapExt, Once};
|
||||
use rustc_data_structures::indexed_vec::{IndexVec, Idx};
|
||||
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder, opaque,
|
||||
|
|
@ -341,11 +342,13 @@ impl<'sess> OnDiskCache<'sess> {
|
|||
/// Store a diagnostic emitted during the current compilation session.
|
||||
/// Anything stored like this will be available via `load_diagnostics` in
|
||||
/// the next compilation session.
|
||||
#[inline(never)]
|
||||
#[cold]
|
||||
pub fn store_diagnostics(&self,
|
||||
dep_node_index: DepNodeIndex,
|
||||
diagnostics: Vec<Diagnostic>) {
|
||||
diagnostics: ThinVec<Diagnostic>) {
|
||||
let mut current_diagnostics = self.current_diagnostics.borrow_mut();
|
||||
let prev = current_diagnostics.insert(dep_node_index, diagnostics);
|
||||
let prev = current_diagnostics.insert(dep_node_index, diagnostics.into());
|
||||
debug_assert!(prev.is_none());
|
||||
}
|
||||
|
||||
|
|
@ -367,16 +370,16 @@ impl<'sess> OnDiskCache<'sess> {
|
|||
/// Since many anonymous queries can share the same `DepNode`, we aggregate
|
||||
/// them -- as opposed to regular queries where we assume that there is a
|
||||
/// 1:1 relationship between query-key and `DepNode`.
|
||||
#[inline(never)]
|
||||
#[cold]
|
||||
pub fn store_diagnostics_for_anon_node(&self,
|
||||
dep_node_index: DepNodeIndex,
|
||||
mut diagnostics: Vec<Diagnostic>) {
|
||||
diagnostics: ThinVec<Diagnostic>) {
|
||||
let mut current_diagnostics = self.current_diagnostics.borrow_mut();
|
||||
|
||||
let x = current_diagnostics.entry(dep_node_index).or_insert_with(|| {
|
||||
mem::replace(&mut diagnostics, Vec::new())
|
||||
});
|
||||
let x = current_diagnostics.entry(dep_node_index).or_insert(Vec::new());
|
||||
|
||||
x.extend(diagnostics.into_iter());
|
||||
x.extend(Into::<Vec<_>>::into(diagnostics));
|
||||
}
|
||||
|
||||
fn load_indexed<'tcx, T>(&self,
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ use util::common::{profq_msg, ProfileQueriesMsg, QueryMsg};
|
|||
|
||||
use rustc_data_structures::fx::{FxHashMap};
|
||||
use rustc_data_structures::sync::{Lrc, Lock};
|
||||
use rustc_data_structures::thin_vec::ThinVec;
|
||||
use std::mem;
|
||||
use std::ptr;
|
||||
use std::collections::hash_map::Entry;
|
||||
|
|
@ -195,19 +196,21 @@ impl<'a, 'tcx, Q: QueryDescription<'tcx>> JobOwner<'a, 'tcx, Q> {
|
|||
pub(super) fn start<'lcx, F, R>(
|
||||
&self,
|
||||
tcx: TyCtxt<'_, 'tcx, 'lcx>,
|
||||
diagnostics: Option<&Lock<ThinVec<Diagnostic>>>,
|
||||
compute: F)
|
||||
-> (R, Vec<Diagnostic>)
|
||||
-> R
|
||||
where
|
||||
F: for<'b> FnOnce(TyCtxt<'b, 'tcx, 'lcx>) -> R
|
||||
{
|
||||
// The TyCtxt stored in TLS has the same global interner lifetime
|
||||
// as `tcx`, so we use `with_related_context` to relate the 'gcx lifetimes
|
||||
// when accessing the ImplicitCtxt
|
||||
let r = tls::with_related_context(tcx, move |current_icx| {
|
||||
tls::with_related_context(tcx, move |current_icx| {
|
||||
// Update the ImplicitCtxt to point to our new query job
|
||||
let new_icx = tls::ImplicitCtxt {
|
||||
tcx: tcx.global_tcx(),
|
||||
query: Some(self.job.clone()),
|
||||
diagnostics,
|
||||
layout_depth: current_icx.layout_depth,
|
||||
task_deps: current_icx.task_deps,
|
||||
};
|
||||
|
|
@ -216,13 +219,19 @@ impl<'a, 'tcx, Q: QueryDescription<'tcx>> JobOwner<'a, 'tcx, Q> {
|
|||
tls::enter_context(&new_icx, |_| {
|
||||
compute(tcx)
|
||||
})
|
||||
});
|
||||
|
||||
// Extract the diagnostic from the job
|
||||
let diagnostics = mem::replace(&mut *self.job.diagnostics.lock(), Vec::new());
|
||||
|
||||
(r, diagnostics)
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn with_diagnostics<F, R>(f: F) -> (R, ThinVec<Diagnostic>)
|
||||
where
|
||||
F: FnOnce(Option<&Lock<ThinVec<Diagnostic>>>) -> R
|
||||
{
|
||||
let diagnostics = Lock::new(ThinVec::new());
|
||||
let result = f(Some(&diagnostics));
|
||||
(result, diagnostics.into_inner())
|
||||
}
|
||||
|
||||
impl<'a, 'tcx, Q: QueryDescription<'tcx>> Drop for JobOwner<'a, 'tcx, Q> {
|
||||
|
|
@ -402,20 +411,23 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
|||
profq_msg!(self, ProfileQueriesMsg::ProviderBegin);
|
||||
self.sess.profiler(|p| p.start_activity(Q::CATEGORY));
|
||||
|
||||
let res = job.start(self, |tcx| {
|
||||
tcx.dep_graph.with_anon_task(dep_node.kind, || {
|
||||
Q::compute(tcx.global_tcx(), key)
|
||||
let ((result, dep_node_index), diagnostics) = with_diagnostics(|diagnostics| {
|
||||
job.start(self, diagnostics, |tcx| {
|
||||
tcx.dep_graph.with_anon_task(dep_node.kind, || {
|
||||
Q::compute(tcx.global_tcx(), key)
|
||||
})
|
||||
})
|
||||
});
|
||||
|
||||
self.sess.profiler(|p| p.end_activity(Q::CATEGORY));
|
||||
profq_msg!(self, ProfileQueriesMsg::ProviderEnd);
|
||||
let ((result, dep_node_index), diagnostics) = res;
|
||||
|
||||
self.dep_graph.read_index(dep_node_index);
|
||||
|
||||
self.queries.on_disk_cache
|
||||
.store_diagnostics_for_anon_node(dep_node_index, diagnostics);
|
||||
if unlikely!(!diagnostics.is_empty()) {
|
||||
self.queries.on_disk_cache
|
||||
.store_diagnostics_for_anon_node(dep_node_index, diagnostics);
|
||||
}
|
||||
|
||||
job.complete(&result, dep_node_index);
|
||||
|
||||
|
|
@ -487,7 +499,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
|||
// The diagnostics for this query have already been
|
||||
// promoted to the current session during
|
||||
// try_mark_green(), so we can ignore them here.
|
||||
let (result, _) = job.start(self, |tcx| {
|
||||
let result = job.start(self, None, |tcx| {
|
||||
// The dep-graph for this computation is already in
|
||||
// place
|
||||
tcx.dep_graph.with_ignore(|| {
|
||||
|
|
@ -566,32 +578,34 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
|||
profq_msg!(self, ProfileQueriesMsg::ProviderBegin);
|
||||
self.sess.profiler(|p| p.start_activity(Q::CATEGORY));
|
||||
|
||||
let res = job.start(self, |tcx| {
|
||||
if dep_node.kind.is_eval_always() {
|
||||
tcx.dep_graph.with_eval_always_task(dep_node,
|
||||
tcx,
|
||||
key,
|
||||
Q::compute)
|
||||
} else {
|
||||
tcx.dep_graph.with_task(dep_node,
|
||||
tcx,
|
||||
key,
|
||||
Q::compute)
|
||||
}
|
||||
let ((result, dep_node_index), diagnostics) = with_diagnostics(|diagnostics| {
|
||||
job.start(self, diagnostics, |tcx| {
|
||||
if dep_node.kind.is_eval_always() {
|
||||
tcx.dep_graph.with_eval_always_task(dep_node,
|
||||
tcx,
|
||||
key,
|
||||
Q::compute)
|
||||
} else {
|
||||
tcx.dep_graph.with_task(dep_node,
|
||||
tcx,
|
||||
key,
|
||||
Q::compute)
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
self.sess.profiler(|p| p.end_activity(Q::CATEGORY));
|
||||
profq_msg!(self, ProfileQueriesMsg::ProviderEnd);
|
||||
|
||||
let ((result, dep_node_index), diagnostics) = res;
|
||||
|
||||
if unlikely!(self.sess.opts.debugging_opts.query_dep_graph) {
|
||||
self.dep_graph.mark_loaded_from_cache(dep_node_index, false);
|
||||
}
|
||||
|
||||
if dep_node.kind != ::dep_graph::DepKind::Null {
|
||||
self.queries.on_disk_cache
|
||||
.store_diagnostics(dep_node_index, diagnostics);
|
||||
if unlikely!(!diagnostics.is_empty()) {
|
||||
self.queries.on_disk_cache
|
||||
.store_diagnostics(dep_node_index, diagnostics);
|
||||
}
|
||||
}
|
||||
|
||||
job.complete(&result, dep_node_index);
|
||||
|
|
|
|||
|
|
@ -1372,7 +1372,14 @@ fn constructor_sub_pattern_tys<'a, 'tcx: 'a>(cx: &MatchCheckCtxt<'a, 'tcx>,
|
|||
let is_visible = adt.is_enum()
|
||||
|| field.vis.is_accessible_from(cx.module, cx.tcx);
|
||||
if is_visible {
|
||||
field.ty(cx.tcx, substs)
|
||||
let ty = field.ty(cx.tcx, substs);
|
||||
match ty.sty {
|
||||
// If the field type returned is an array of an unknown
|
||||
// size return an TyErr.
|
||||
ty::Array(_, len) if len.assert_usize(cx.tcx).is_none() =>
|
||||
cx.tcx.types.err,
|
||||
_ => ty,
|
||||
}
|
||||
} else {
|
||||
// Treat all non-visible fields as TyErr. They
|
||||
// can't appear in any other pattern from
|
||||
|
|
|
|||
|
|
@ -20,21 +20,33 @@ use std::cmp;
|
|||
use super::report_unexpected_variant_def;
|
||||
|
||||
impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
/// The `is_arg` argument indicates whether this pattern is the
|
||||
/// *outermost* pattern in an argument (e.g., in `fn foo(&x:
|
||||
/// &u32)`, it is true for the `&x` pattern but not `x`). This is
|
||||
/// used to tailor error reporting.
|
||||
/// `match_discrim_span` argument having a `Span` indicates that this pattern is part of
|
||||
/// a match expression arm guard, and it points to the match discriminant to add context
|
||||
/// in type errors. In the folloowing example, `match_discrim_span` corresponds to the
|
||||
/// `a + b` expression:
|
||||
///
|
||||
/// ```text
|
||||
/// error[E0308]: mismatched types
|
||||
/// --> src/main.rs:5:9
|
||||
/// |
|
||||
/// 4 | let temp: usize = match a + b {
|
||||
/// | ----- this expression has type `usize`
|
||||
/// 5 | Ok(num) => num,
|
||||
/// | ^^^^^^^ expected usize, found enum `std::result::Result`
|
||||
/// |
|
||||
/// = note: expected type `usize`
|
||||
/// found type `std::result::Result<_, _>`
|
||||
/// ```
|
||||
pub fn check_pat_walk(
|
||||
&self,
|
||||
pat: &'gcx hir::Pat,
|
||||
mut expected: Ty<'tcx>,
|
||||
mut def_bm: ty::BindingMode,
|
||||
is_arg: bool)
|
||||
{
|
||||
match_discrim_span: Option<Span>,
|
||||
) {
|
||||
let tcx = self.tcx;
|
||||
|
||||
debug!("check_pat_walk(pat={:?},expected={:?},def_bm={:?},is_arg={})",
|
||||
pat, expected, def_bm, is_arg);
|
||||
debug!("check_pat_walk(pat={:?},expected={:?},def_bm={:?})", pat, expected, def_bm);
|
||||
|
||||
let is_non_ref_pat = match pat.node {
|
||||
PatKind::Struct(..) |
|
||||
|
|
@ -210,8 +222,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
let common_type = self.resolve_type_vars_if_possible(&lhs_ty);
|
||||
|
||||
// subtyping doesn't matter here, as the value is some kind of scalar
|
||||
self.demand_eqtype(pat.span, expected, lhs_ty);
|
||||
self.demand_eqtype(pat.span, expected, rhs_ty);
|
||||
self.demand_eqtype_pat(pat.span, expected, lhs_ty, match_discrim_span);
|
||||
self.demand_eqtype_pat(pat.span, expected, rhs_ty, match_discrim_span);
|
||||
common_type
|
||||
}
|
||||
PatKind::Binding(ba, var_id, _, ref sub) => {
|
||||
|
|
@ -240,13 +252,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
// `x` is assigned a value of type `&M T`, hence `&M T <: typeof(x)` is
|
||||
// required. However, we use equality, which is stronger. See (*) for
|
||||
// an explanation.
|
||||
self.demand_eqtype(pat.span, region_ty, local_ty);
|
||||
self.demand_eqtype_pat(pat.span, region_ty, local_ty, match_discrim_span);
|
||||
}
|
||||
// otherwise the type of x is the expected type T
|
||||
ty::BindByValue(_) => {
|
||||
// As above, `T <: typeof(x)` is required but we
|
||||
// use equality, see (*) below.
|
||||
self.demand_eqtype(pat.span, expected, local_ty);
|
||||
self.demand_eqtype_pat(pat.span, expected, local_ty, match_discrim_span);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -254,23 +266,31 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
// what the type of the binding `x` ought to be
|
||||
if var_id != pat.id {
|
||||
let vt = self.local_ty(pat.span, var_id).decl_ty;
|
||||
self.demand_eqtype(pat.span, vt, local_ty);
|
||||
self.demand_eqtype_pat(pat.span, vt, local_ty, match_discrim_span);
|
||||
}
|
||||
|
||||
if let Some(ref p) = *sub {
|
||||
self.check_pat_walk(&p, expected, def_bm, true);
|
||||
self.check_pat_walk(&p, expected, def_bm, match_discrim_span);
|
||||
}
|
||||
|
||||
local_ty
|
||||
}
|
||||
PatKind::TupleStruct(ref qpath, ref subpats, ddpos) => {
|
||||
self.check_pat_tuple_struct(pat, qpath, &subpats, ddpos, expected, def_bm)
|
||||
self.check_pat_tuple_struct(
|
||||
pat,
|
||||
qpath,
|
||||
&subpats,
|
||||
ddpos,
|
||||
expected,
|
||||
def_bm,
|
||||
match_discrim_span,
|
||||
)
|
||||
}
|
||||
PatKind::Path(ref qpath) => {
|
||||
self.check_pat_path(pat, qpath, expected)
|
||||
}
|
||||
PatKind::Struct(ref qpath, ref fields, etc) => {
|
||||
self.check_pat_struct(pat, qpath, fields, etc, expected, def_bm)
|
||||
self.check_pat_struct(pat, qpath, fields, etc, expected, def_bm, match_discrim_span)
|
||||
}
|
||||
PatKind::Tuple(ref elements, ddpos) => {
|
||||
let mut expected_len = elements.len();
|
||||
|
|
@ -295,12 +315,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
// further errors being emitted when using the bindings. #50333
|
||||
let element_tys_iter = (0..max_len).map(|_| tcx.types.err);
|
||||
for (_, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) {
|
||||
self.check_pat_walk(elem, &tcx.types.err, def_bm, true);
|
||||
self.check_pat_walk(elem, &tcx.types.err, def_bm, match_discrim_span);
|
||||
}
|
||||
tcx.mk_tup(element_tys_iter)
|
||||
} else {
|
||||
for (i, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) {
|
||||
self.check_pat_walk(elem, &element_tys[i], def_bm, true);
|
||||
self.check_pat_walk(elem, &element_tys[i], def_bm, match_discrim_span);
|
||||
}
|
||||
pat_ty
|
||||
}
|
||||
|
|
@ -313,11 +333,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
// Here, `demand::subtype` is good enough, but I don't
|
||||
// think any errors can be introduced by using
|
||||
// `demand::eqtype`.
|
||||
self.demand_eqtype(pat.span, expected, uniq_ty);
|
||||
self.check_pat_walk(&inner, inner_ty, def_bm, true);
|
||||
self.demand_eqtype_pat(pat.span, expected, uniq_ty, match_discrim_span);
|
||||
self.check_pat_walk(&inner, inner_ty, def_bm, match_discrim_span);
|
||||
uniq_ty
|
||||
} else {
|
||||
self.check_pat_walk(&inner, tcx.types.err, def_bm, true);
|
||||
self.check_pat_walk(&inner, tcx.types.err, def_bm, match_discrim_span);
|
||||
tcx.types.err
|
||||
}
|
||||
}
|
||||
|
|
@ -349,15 +369,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
// Look for a case like `fn foo(&foo: u32)` and suggest
|
||||
// `fn foo(foo: &u32)`
|
||||
if let Some(mut err) = err {
|
||||
if is_arg {
|
||||
if let PatKind::Binding(..) = inner.node {
|
||||
if let Ok(snippet) = tcx.sess.source_map()
|
||||
.span_to_snippet(pat.span)
|
||||
{
|
||||
err.help(&format!("did you mean `{}: &{}`?",
|
||||
&snippet[1..],
|
||||
expected));
|
||||
}
|
||||
if let PatKind::Binding(..) = inner.node {
|
||||
if let Ok(snippet) = tcx.sess.source_map()
|
||||
.span_to_snippet(pat.span)
|
||||
{
|
||||
err.help(&format!("did you mean `{}: &{}`?",
|
||||
&snippet[1..],
|
||||
expected));
|
||||
}
|
||||
}
|
||||
err.emit();
|
||||
|
|
@ -366,10 +384,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
}
|
||||
};
|
||||
|
||||
self.check_pat_walk(&inner, inner_ty, def_bm, true);
|
||||
self.check_pat_walk(&inner, inner_ty, def_bm, match_discrim_span);
|
||||
rptr_ty
|
||||
} else {
|
||||
self.check_pat_walk(&inner, tcx.types.err, def_bm, true);
|
||||
self.check_pat_walk(&inner, tcx.types.err, def_bm, match_discrim_span);
|
||||
tcx.types.err
|
||||
}
|
||||
}
|
||||
|
|
@ -427,13 +445,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
};
|
||||
|
||||
for elt in before {
|
||||
self.check_pat_walk(&elt, inner_ty, def_bm, true);
|
||||
self.check_pat_walk(&elt, inner_ty, def_bm, match_discrim_span);
|
||||
}
|
||||
if let Some(ref slice) = *slice {
|
||||
self.check_pat_walk(&slice, slice_ty, def_bm, true);
|
||||
self.check_pat_walk(&slice, slice_ty, def_bm, match_discrim_span);
|
||||
}
|
||||
for elt in after {
|
||||
self.check_pat_walk(&elt, inner_ty, def_bm, true);
|
||||
self.check_pat_walk(&elt, inner_ty, def_bm, match_discrim_span);
|
||||
}
|
||||
expected_ty
|
||||
}
|
||||
|
|
@ -524,12 +542,14 @@ https://doc.rust-lang.org/reference/types.html#trait-objects");
|
|||
true
|
||||
}
|
||||
|
||||
pub fn check_match(&self,
|
||||
expr: &'gcx hir::Expr,
|
||||
discrim: &'gcx hir::Expr,
|
||||
arms: &'gcx [hir::Arm],
|
||||
expected: Expectation<'tcx>,
|
||||
match_src: hir::MatchSource) -> Ty<'tcx> {
|
||||
pub fn check_match(
|
||||
&self,
|
||||
expr: &'gcx hir::Expr,
|
||||
discrim: &'gcx hir::Expr,
|
||||
arms: &'gcx [hir::Arm],
|
||||
expected: Expectation<'tcx>,
|
||||
match_src: hir::MatchSource,
|
||||
) -> Ty<'tcx> {
|
||||
let tcx = self.tcx;
|
||||
|
||||
// Not entirely obvious: if matches may create ref bindings, we want to
|
||||
|
|
@ -624,8 +644,12 @@ https://doc.rust-lang.org/reference/types.html#trait-objects");
|
|||
let mut all_pats_diverge = Diverges::WarnedAlways;
|
||||
for p in &arm.pats {
|
||||
self.diverges.set(Diverges::Maybe);
|
||||
self.check_pat_walk(&p, discrim_ty,
|
||||
ty::BindingMode::BindByValue(hir::Mutability::MutImmutable), true);
|
||||
self.check_pat_walk(
|
||||
&p,
|
||||
discrim_ty,
|
||||
ty::BindingMode::BindByValue(hir::Mutability::MutImmutable),
|
||||
Some(discrim.span),
|
||||
);
|
||||
all_pats_diverge &= self.diverges.get();
|
||||
}
|
||||
|
||||
|
|
@ -703,26 +727,34 @@ https://doc.rust-lang.org/reference/types.html#trait-objects");
|
|||
coercion.complete(self)
|
||||
}
|
||||
|
||||
fn check_pat_struct(&self,
|
||||
pat: &'gcx hir::Pat,
|
||||
qpath: &hir::QPath,
|
||||
fields: &'gcx [Spanned<hir::FieldPat>],
|
||||
etc: bool,
|
||||
expected: Ty<'tcx>,
|
||||
def_bm: ty::BindingMode) -> Ty<'tcx>
|
||||
fn check_pat_struct(
|
||||
&self,
|
||||
pat: &'gcx hir::Pat,
|
||||
qpath: &hir::QPath,
|
||||
fields: &'gcx [Spanned<hir::FieldPat>],
|
||||
etc: bool,
|
||||
expected: Ty<'tcx>,
|
||||
def_bm: ty::BindingMode,
|
||||
match_discrim_span: Option<Span>,
|
||||
) -> Ty<'tcx>
|
||||
{
|
||||
// Resolve the path and check the definition for errors.
|
||||
let (variant, pat_ty) = if let Some(variant_ty) = self.check_struct_path(qpath, pat.id) {
|
||||
variant_ty
|
||||
} else {
|
||||
for field in fields {
|
||||
self.check_pat_walk(&field.node.pat, self.tcx.types.err, def_bm, true);
|
||||
self.check_pat_walk(
|
||||
&field.node.pat,
|
||||
self.tcx.types.err,
|
||||
def_bm,
|
||||
match_discrim_span,
|
||||
);
|
||||
}
|
||||
return self.tcx.types.err;
|
||||
};
|
||||
|
||||
// Type-check the path.
|
||||
self.demand_eqtype(pat.span, expected, pat_ty);
|
||||
self.demand_eqtype_pat(pat.span, expected, pat_ty, match_discrim_span);
|
||||
|
||||
// Type-check subpatterns.
|
||||
if self.check_struct_pat_fields(pat_ty, pat.id, pat.span, variant, fields, etc, def_bm) {
|
||||
|
|
@ -732,11 +764,12 @@ https://doc.rust-lang.org/reference/types.html#trait-objects");
|
|||
}
|
||||
}
|
||||
|
||||
fn check_pat_path(&self,
|
||||
pat: &hir::Pat,
|
||||
qpath: &hir::QPath,
|
||||
expected: Ty<'tcx>) -> Ty<'tcx>
|
||||
{
|
||||
fn check_pat_path(
|
||||
&self,
|
||||
pat: &hir::Pat,
|
||||
qpath: &hir::QPath,
|
||||
expected: Ty<'tcx>,
|
||||
) -> Ty<'tcx> {
|
||||
let tcx = self.tcx;
|
||||
|
||||
// Resolve the path and check the definition for errors.
|
||||
|
|
@ -767,18 +800,20 @@ https://doc.rust-lang.org/reference/types.html#trait-objects");
|
|||
pat_ty
|
||||
}
|
||||
|
||||
fn check_pat_tuple_struct(&self,
|
||||
pat: &hir::Pat,
|
||||
qpath: &hir::QPath,
|
||||
subpats: &'gcx [P<hir::Pat>],
|
||||
ddpos: Option<usize>,
|
||||
expected: Ty<'tcx>,
|
||||
def_bm: ty::BindingMode) -> Ty<'tcx>
|
||||
{
|
||||
fn check_pat_tuple_struct(
|
||||
&self,
|
||||
pat: &hir::Pat,
|
||||
qpath: &hir::QPath,
|
||||
subpats: &'gcx [P<hir::Pat>],
|
||||
ddpos: Option<usize>,
|
||||
expected: Ty<'tcx>,
|
||||
def_bm: ty::BindingMode,
|
||||
match_arm_pat_span: Option<Span>,
|
||||
) -> Ty<'tcx> {
|
||||
let tcx = self.tcx;
|
||||
let on_error = || {
|
||||
for pat in subpats {
|
||||
self.check_pat_walk(&pat, tcx.types.err, def_bm, true);
|
||||
self.check_pat_walk(&pat, tcx.types.err, def_bm, match_arm_pat_span);
|
||||
}
|
||||
};
|
||||
let report_unexpected_def = |def: Def| {
|
||||
|
|
@ -826,7 +861,7 @@ https://doc.rust-lang.org/reference/types.html#trait-objects");
|
|||
let pat_ty = pat_ty.fn_sig(tcx).output();
|
||||
let pat_ty = pat_ty.no_bound_vars().expect("expected fn type");
|
||||
|
||||
self.demand_eqtype(pat.span, expected, pat_ty);
|
||||
self.demand_eqtype_pat(pat.span, expected, pat_ty, match_arm_pat_span);
|
||||
|
||||
// Type-check subpatterns.
|
||||
if subpats.len() == variant.fields.len() ||
|
||||
|
|
@ -837,7 +872,7 @@ https://doc.rust-lang.org/reference/types.html#trait-objects");
|
|||
};
|
||||
for (i, subpat) in subpats.iter().enumerate_and_adjust(variant.fields.len(), ddpos) {
|
||||
let field_ty = self.field_ty(subpat.span, &variant.fields[i], substs);
|
||||
self.check_pat_walk(&subpat, field_ty, def_bm, true);
|
||||
self.check_pat_walk(&subpat, field_ty, def_bm, match_arm_pat_span);
|
||||
|
||||
self.tcx.check_stability(variant.fields[i].did, Some(pat.id), subpat.span);
|
||||
}
|
||||
|
|
@ -917,7 +952,7 @@ https://doc.rust-lang.org/reference/types.html#trait-objects");
|
|||
}
|
||||
};
|
||||
|
||||
self.check_pat_walk(&field.pat, field_ty, def_bm, true);
|
||||
self.check_pat_walk(&field.pat, field_ty, def_bm, None);
|
||||
}
|
||||
let mut unmentioned_fields = variant.fields
|
||||
.iter()
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use check::FnCtxt;
|
||||
use rustc::infer::InferOk;
|
||||
use rustc::traits::ObligationCause;
|
||||
use rustc::traits::{ObligationCause, ObligationCauseCode};
|
||||
|
||||
use syntax::ast;
|
||||
use syntax::util::parser::PREC_POSTFIX;
|
||||
|
|
@ -66,6 +66,25 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn demand_eqtype_pat(
|
||||
&self,
|
||||
cause_span: Span,
|
||||
expected: Ty<'tcx>,
|
||||
actual: Ty<'tcx>,
|
||||
match_expr_span: Option<Span>,
|
||||
) {
|
||||
let cause = if let Some(span) = match_expr_span {
|
||||
self.cause(
|
||||
cause_span,
|
||||
ObligationCauseCode::MatchExpressionArmPattern { span, ty: expected },
|
||||
)
|
||||
} else {
|
||||
self.misc(cause_span)
|
||||
};
|
||||
self.demand_eqtype_with_origin(&cause, expected, actual).map(|mut err| err.emit());
|
||||
}
|
||||
|
||||
|
||||
pub fn demand_coerce(&self,
|
||||
expr: &hir::Expr,
|
||||
checked_ty: Ty<'tcx>,
|
||||
|
|
|
|||
|
|
@ -1092,8 +1092,12 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>,
|
|||
// Add formal parameters.
|
||||
for (arg_ty, arg) in fn_sig.inputs().iter().zip(&body.arguments) {
|
||||
// Check the pattern.
|
||||
fcx.check_pat_walk(&arg.pat, arg_ty,
|
||||
ty::BindingMode::BindByValue(hir::Mutability::MutImmutable), true);
|
||||
fcx.check_pat_walk(
|
||||
&arg.pat,
|
||||
arg_ty,
|
||||
ty::BindingMode::BindByValue(hir::Mutability::MutImmutable),
|
||||
None,
|
||||
);
|
||||
|
||||
// Check that argument is Sized.
|
||||
// The check for a non-trivial pattern is a hack to avoid duplicate warnings
|
||||
|
|
@ -4731,9 +4735,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
self.check_pat_walk(&local.pat, t,
|
||||
ty::BindingMode::BindByValue(hir::Mutability::MutImmutable),
|
||||
true);
|
||||
self.check_pat_walk(
|
||||
&local.pat,
|
||||
t,
|
||||
ty::BindingMode::BindByValue(hir::Mutability::MutImmutable),
|
||||
None,
|
||||
);
|
||||
let pat_ty = self.node_ty(local.pat.hir_id);
|
||||
if pat_ty.references_error() {
|
||||
self.write_ty(local.hir_id, pat_ty);
|
||||
|
|
|
|||
|
|
@ -3059,7 +3059,7 @@ fn item_trait(
|
|||
let item_type = m.type_();
|
||||
let id = cx.derive_id(format!("{}.{}", item_type, name));
|
||||
let ns_id = cx.derive_id(format!("{}.{}", name, item_type.name_space()));
|
||||
write!(w, "{extra}<h3 id='{id}' class='method'><code id='{ns_id}'>",
|
||||
write!(w, "<h3 id='{id}' class='method'>{extra}<code id='{ns_id}'>",
|
||||
extra = render_spotlight_traits(m)?,
|
||||
id = id,
|
||||
ns_id = ns_id)?;
|
||||
|
|
@ -3444,7 +3444,7 @@ fn item_union(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
|
|||
let id = format!("{}.{}", ItemType::StructField, name);
|
||||
write!(w, "<span id=\"{id}\" class=\"{shortty} small-section-header\">\
|
||||
<a href=\"#{id}\" class=\"anchor field\"></a>\
|
||||
<span class='invisible'><code>{name}: {ty}</code></span>\
|
||||
<code>{name}: {ty}</code>\
|
||||
</span>",
|
||||
id = id,
|
||||
name = name,
|
||||
|
|
@ -3999,8 +3999,7 @@ fn render_impl(w: &mut fmt::Formatter, cx: &Context, i: &Impl, link: AssocItemLi
|
|||
None => "impl".to_string(),
|
||||
});
|
||||
if let Some(use_absolute) = use_absolute {
|
||||
write!(w, "<h3 id='{}' class='impl'><span class='in-band'><table class='table-display'>\
|
||||
<tbody><tr><td><code>", id)?;
|
||||
write!(w, "<h3 id='{}' class='impl'><code class='in-band'>", id)?;
|
||||
fmt_impl_for_trait_page(&i.inner_impl(), w, use_absolute)?;
|
||||
if show_def_docs {
|
||||
for it in &i.inner_impl().items {
|
||||
|
|
@ -4014,22 +4013,18 @@ fn render_impl(w: &mut fmt::Formatter, cx: &Context, i: &Impl, link: AssocItemLi
|
|||
}
|
||||
write!(w, "</code>")?;
|
||||
} else {
|
||||
write!(w, "<h3 id='{}' class='impl'><span class='in-band'><table class='table-display'>\
|
||||
<tbody><tr><td><code>{}</code>",
|
||||
id, i.inner_impl())?;
|
||||
write!(w, "<h3 id='{}' class='impl'><code class='in-band'>{}</code>",
|
||||
id, i.inner_impl()
|
||||
)?;
|
||||
}
|
||||
write!(w, "<a href='#{}' class='anchor'></a>", id)?;
|
||||
write!(w, "</td><td><span class='out-of-band'>")?;
|
||||
let since = i.impl_item.stability.as_ref().map(|s| &s.since[..]);
|
||||
render_stability_since_raw(w, since, outer_version)?;
|
||||
if let Some(l) = (Item { item: &i.impl_item, cx: cx }).src_href() {
|
||||
write!(w, "<div class='ghost'></div>")?;
|
||||
render_stability_since_raw(w, since, outer_version)?;
|
||||
write!(w, "<a class='srclink' href='{}' title='{}'>[src]</a>",
|
||||
l, "goto source code")?;
|
||||
} else {
|
||||
render_stability_since_raw(w, since, outer_version)?;
|
||||
}
|
||||
write!(w, "</span></td></tr></tbody></table></span></h3>")?;
|
||||
write!(w, "</h3>")?;
|
||||
if let Some(ref dox) = cx.shared.maybe_collapsed_doc_value(&i.impl_item) {
|
||||
let mut ids = cx.id_map.borrow_mut();
|
||||
write!(w, "<div class='docblock'>{}</div>",
|
||||
|
|
@ -4065,20 +4060,15 @@ fn render_impl(w: &mut fmt::Formatter, cx: &Context, i: &Impl, link: AssocItemLi
|
|||
let ns_id = cx.derive_id(format!("{}.{}", name, item_type.name_space()));
|
||||
write!(w, "<h4 id='{}' class=\"{}{}\">", id, item_type, extra_class)?;
|
||||
write!(w, "{}", spotlight_decl(decl)?)?;
|
||||
write!(w, "<table id='{}' class='table-display'><tbody><tr><td><code>", ns_id)?;
|
||||
write!(w, "<code id='{}'>", ns_id)?;
|
||||
render_assoc_item(w, item, link.anchor(&id), ItemType::Impl)?;
|
||||
write!(w, "</code>")?;
|
||||
render_stability_since_raw(w, item.stable_since(), outer_version)?;
|
||||
if let Some(l) = (Item { cx, item }).src_href() {
|
||||
write!(w, "</td><td><span class='out-of-band'>")?;
|
||||
write!(w, "<div class='ghost'></div>")?;
|
||||
render_stability_since_raw(w, item.stable_since(), outer_version)?;
|
||||
write!(w, "<a class='srclink' href='{}' title='{}'>[src]</a></span>",
|
||||
write!(w, "<a class='srclink' href='{}' title='{}'>[src]</a>",
|
||||
l, "goto source code")?;
|
||||
} else {
|
||||
write!(w, "</td><td>")?;
|
||||
render_stability_since_raw(w, item.stable_since(), outer_version)?;
|
||||
}
|
||||
write!(w, "</td></tr></tbody></table></h4>")?;
|
||||
write!(w, "</h4>")?;
|
||||
}
|
||||
}
|
||||
clean::TypedefItem(ref tydef, _) => {
|
||||
|
|
@ -4090,40 +4080,18 @@ fn render_impl(w: &mut fmt::Formatter, cx: &Context, i: &Impl, link: AssocItemLi
|
|||
write!(w, "</code></h4>")?;
|
||||
}
|
||||
clean::AssociatedConstItem(ref ty, ref default) => {
|
||||
let mut version = String::new();
|
||||
|
||||
render_stability_since_raw(&mut version, item.stable_since(), outer_version)?;
|
||||
|
||||
let id = cx.derive_id(format!("{}.{}", item_type, name));
|
||||
let ns_id = cx.derive_id(format!("{}.{}", name, item_type.name_space()));
|
||||
write!(w, "<h4 id='{}' class=\"{}{}\">", id, item_type, extra_class)?;
|
||||
if !version.is_empty() {
|
||||
write!(w, "<table id='{}' class='table-display'><tbody><tr><td><code>", ns_id)?;
|
||||
} else {
|
||||
write!(w, "<code id='{}'>", ns_id)?;
|
||||
}
|
||||
write!(w, "<code id='{}'>", ns_id)?;
|
||||
assoc_const(w, item, ty, default.as_ref(), link.anchor(&id))?;
|
||||
if !version.is_empty() {
|
||||
write!(w, "</code>")?;
|
||||
}
|
||||
let src = if let Some(l) = (Item { cx, item }).src_href() {
|
||||
if !version.is_empty() {
|
||||
write!(w, "</td><td><span class='out-of-band'>")?;
|
||||
write!(w, "<div class='ghost'></div>{}", version)?;
|
||||
}
|
||||
format!("<a class='srclink' href='{}' title='{}'>[src]</a>",
|
||||
l, "goto source code")
|
||||
} else {
|
||||
if !version.is_empty() {
|
||||
write!(w, "</td><td>{}", version)?;
|
||||
}
|
||||
String::new()
|
||||
};
|
||||
if version.is_empty() {
|
||||
write!(w, "</code>{}</h4>", src)?;
|
||||
} else {
|
||||
write!(w, "{}</span></td></tr></tbody></table></h4>", src)?;
|
||||
write!(w, "</code>")?;
|
||||
render_stability_since_raw(w, item.stable_since(), outer_version)?;
|
||||
if let Some(l) = (Item { cx, item }).src_href() {
|
||||
write!(w, "<a class='srclink' href='{}' title='{}'>[src]</a>",
|
||||
l, "goto source code")?;
|
||||
}
|
||||
write!(w, "</h4>")?;
|
||||
}
|
||||
clean::AssociatedTypeItem(ref bounds, ref default) => {
|
||||
let id = cx.derive_id(format!("{}.{}", item_type, name));
|
||||
|
|
|
|||
|
|
@ -2409,8 +2409,17 @@ if (!DOMTokenList.prototype.remove) {
|
|||
e.remove();
|
||||
});
|
||||
onEachLazy(main.childNodes, function(e) {
|
||||
// Unhide the actual content once loading is complete. Headers get
|
||||
// flex treatment for their horizontal layout, divs get block treatment
|
||||
// for vertical layout (column-oriented flex layout for divs caused
|
||||
// errors in mobile browsers).
|
||||
if (e.tagName === "H2" || e.tagName === "H3") {
|
||||
e.nextElementSibling.style.display = "block";
|
||||
let nextTagName = e.nextElementSibling.tagName;
|
||||
if (nextTagName == "H2" || nextTagName == "H3") {
|
||||
e.nextElementSibling.style.display = "flex";
|
||||
} else {
|
||||
e.nextElementSibling.style.display = "block";
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -89,8 +89,9 @@ h2, h3:not(.impl):not(.method):not(.type):not(.tymethod), h4:not(.method):not(.t
|
|||
border-bottom: 1px solid;
|
||||
}
|
||||
h3.impl, h3.method, h4.method, h3.type, h4.type, h4.associatedconstant {
|
||||
flex-basis: 100%;
|
||||
font-weight: 600;
|
||||
margin-top: 10px;
|
||||
margin-top: 16px;
|
||||
margin-bottom: 10px;
|
||||
position: relative;
|
||||
}
|
||||
|
|
@ -356,7 +357,8 @@ nav.sub {
|
|||
#main > .docblock h3, #main > .docblock h4, #main > .docblock h5 { font-size: 1em; }
|
||||
|
||||
#main > h2 + div, #main > h2 + h3, #main > h3 + div {
|
||||
display: none;
|
||||
display: none; /* Changed to flex or block via js once the page is loaded */
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.docblock h1 { font-size: 1em; }
|
||||
|
|
@ -390,7 +392,7 @@ h4 > code, h3 > code, .invisible > code {
|
|||
}
|
||||
|
||||
.in-band, code {
|
||||
z-index: 5;
|
||||
z-index: -5;
|
||||
}
|
||||
|
||||
.invisible {
|
||||
|
|
@ -534,6 +536,10 @@ h4 > code, h3 > code, .invisible > code {
|
|||
margin-top: -8px;
|
||||
}
|
||||
|
||||
.impl-items {
|
||||
flex-basis: 100%;
|
||||
}
|
||||
|
||||
#main > .stability {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
|
@ -784,6 +790,33 @@ body.blur > :not(#help) {
|
|||
top: 0;
|
||||
}
|
||||
|
||||
.impl-items .since, .impl .since {
|
||||
flex-grow: 0;
|
||||
padding-left: 12px;
|
||||
padding-right: 2px;
|
||||
position: initial;
|
||||
}
|
||||
|
||||
.impl-items .srclink, .impl .srclink {
|
||||
flex-grow: 0;
|
||||
/* Override header settings otherwise it's too bold */
|
||||
font-size: 17px;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.impl-items code, .impl code {
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.impl-items h4, h4.impl, h3.impl {
|
||||
display: flex;
|
||||
flex-basis: 100%;
|
||||
font-size: 16px;
|
||||
margin-bottom: 12px;
|
||||
/* Push the src link out to the right edge consistently */
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.variants_table {
|
||||
width: 100%;
|
||||
}
|
||||
|
|
@ -871,15 +904,6 @@ h3 > .collapse-toggle, h4 > .collapse-toggle {
|
|||
margin-left: 20px;
|
||||
}
|
||||
|
||||
.ghost {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.ghost + .since {
|
||||
position: initial;
|
||||
display: table-cell;
|
||||
}
|
||||
|
||||
.since + .srclink {
|
||||
display: table-cell;
|
||||
padding-left: 10px;
|
||||
|
|
@ -1119,7 +1143,7 @@ span.since {
|
|||
margin-left: 5px;
|
||||
top: -5px;
|
||||
left: 105%;
|
||||
z-index: 1;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.tooltip:hover .tooltiptext {
|
||||
|
|
@ -1361,8 +1385,9 @@ h3.important {
|
|||
margin-top: 16px;
|
||||
}
|
||||
|
||||
.content > .methods > div.important-traits {
|
||||
.content > .methods > .method > div.important-traits {
|
||||
position: absolute;
|
||||
font-weight: 400;
|
||||
left: -42px;
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
pub struct SomeStruct;
|
||||
|
||||
impl SomeStruct {
|
||||
// @has 'foo/struct.SomeStruct.html' '//*[@id="SOME_CONST.v"]//div[@class="since"]' '1.1.2'
|
||||
// @has 'foo/struct.SomeStruct.html' '//*[@id="associatedconstant.SOME_CONST"]//div[@class="since"]' '1.1.2'
|
||||
#[stable(since="1.1.2", feature="rust2")]
|
||||
pub const SOME_CONST: usize = 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
pub struct Foo;
|
||||
|
||||
impl Foo {
|
||||
// @has const/struct.Foo.html '//*[@id="new.v"]//code' 'const unsafe fn new'
|
||||
// @has const/struct.Foo.html '//code[@id="new.v"]' 'const unsafe fn new'
|
||||
pub const unsafe fn new() -> Foo {
|
||||
Foo
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,17 +9,17 @@ pub trait Bar {
|
|||
|
||||
impl Foo<u8> {
|
||||
// @has - '//*[@id="method.pass"]//code' 'fn pass()'
|
||||
// @has - '//*[@id="pass.v"]//code' 'fn pass()'
|
||||
// @has - '//code[@id="pass.v"]' 'fn pass()'
|
||||
pub fn pass() {}
|
||||
}
|
||||
impl Foo<u16> {
|
||||
// @has - '//*[@id="method.pass-1"]//code' 'fn pass() -> usize'
|
||||
// @has - '//*[@id="pass.v-1"]//code' 'fn pass() -> usize'
|
||||
// @has - '//code[@id="pass.v-1"]' 'fn pass() -> usize'
|
||||
pub fn pass() -> usize { 42 }
|
||||
}
|
||||
impl Foo<u32> {
|
||||
// @has - '//*[@id="method.pass-2"]//code' 'fn pass() -> isize'
|
||||
// @has - '//*[@id="pass.v-2"]//code' 'fn pass() -> isize'
|
||||
// @has - '//code[@id="pass.v-2"]' 'fn pass() -> isize'
|
||||
pub fn pass() -> isize { 42 }
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ pub mod traits {
|
|||
}
|
||||
|
||||
// @has issue_51236/struct.Owned.html
|
||||
// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//*/code' "impl<T> Send for \
|
||||
// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//code' "impl<T> Send for \
|
||||
// Owned<T> where <T as Owned<'static>>::Reader: Send"
|
||||
pub struct Owned<T> where T: for<'a> ::traits::Owned<'a> {
|
||||
marker: PhantomData<<T as ::traits::Owned<'static>>::Reader>,
|
||||
|
|
|
|||
|
|
@ -3,10 +3,10 @@ pub trait ScopeHandle<'scope> {}
|
|||
|
||||
|
||||
// @has issue_54705/struct.ScopeFutureContents.html
|
||||
// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//*/code' "impl<'scope, S> \
|
||||
// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//code' "impl<'scope, S> \
|
||||
// Send for ScopeFutureContents<'scope, S> where S: Sync"
|
||||
//
|
||||
// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//*/code' "impl<'scope, S> \
|
||||
// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//code' "impl<'scope, S> \
|
||||
// Sync for ScopeFutureContents<'scope, S> where S: Sync"
|
||||
pub struct ScopeFutureContents<'scope, S>
|
||||
where S: ScopeHandle<'scope>,
|
||||
|
|
|
|||
|
|
@ -1,16 +1,16 @@
|
|||
#![feature(optin_builtin_traits)]
|
||||
|
||||
// @has issue_55321/struct.A.html
|
||||
// @has - '//*[@id="implementations-list"]/*[@class="impl"]//*/code' "impl !Send for A"
|
||||
// @has - '//*[@id="implementations-list"]/*[@class="impl"]//*/code' "impl !Sync for A"
|
||||
// @has - '//*[@id="implementations-list"]/*[@class="impl"]//code' "impl !Send for A"
|
||||
// @has - '//*[@id="implementations-list"]/*[@class="impl"]//code' "impl !Sync for A"
|
||||
pub struct A();
|
||||
|
||||
impl !Send for A {}
|
||||
impl !Sync for A {}
|
||||
|
||||
// @has issue_55321/struct.B.html
|
||||
// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//*/code' "impl<T> !Send for \
|
||||
// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//code' "impl<T> !Send for \
|
||||
// B<T>"
|
||||
// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//*/code' "impl<T> !Sync for \
|
||||
// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//code' "impl<T> !Sync for \
|
||||
// B<T>"
|
||||
pub struct B<T: ?Sized>(A, Box<T>);
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ impl<'a, T> MyTrait for Inner<'a, T> {
|
|||
}
|
||||
|
||||
// @has issue_56822/struct.Parser.html
|
||||
// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//*/code' "impl<'a> Send for \
|
||||
// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//code' "impl<'a> Send for \
|
||||
// Parser<'a>"
|
||||
pub struct Parser<'a> {
|
||||
field: <Wrapper<Inner<'a, u8>> as MyTrait>::Output
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ mod foo {
|
|||
}
|
||||
|
||||
// @has complex/struct.NotOuter.html
|
||||
// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//*/code' "impl<'a, T, K: \
|
||||
// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//code' "impl<'a, T, K: \
|
||||
// ?Sized> Send for NotOuter<'a, T, K> where K: for<'b> Fn((&'b bool, &'a u8)) \
|
||||
// -> &'b i8, T: MyTrait<'a>, <T as MyTrait<'a>>::MyItem: Copy, 'a: 'static"
|
||||
|
||||
|
|
|
|||
|
|
@ -9,10 +9,10 @@ where
|
|||
{}
|
||||
|
||||
// @has lifetimes/struct.Foo.html
|
||||
// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//*/code' "impl<'c, K> Send \
|
||||
// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//code' "impl<'c, K> Send \
|
||||
// for Foo<'c, K> where K: for<'b> Fn(&'b bool) -> &'c u8, 'c: 'static"
|
||||
//
|
||||
// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//*/code' "impl<'c, K> Sync \
|
||||
// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//code' "impl<'c, K> Sync \
|
||||
// for Foo<'c, K> where K: Sync"
|
||||
pub struct Foo<'c, K: 'c> {
|
||||
inner_field: Inner<'c, K>,
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
// @has manual/struct.Foo.html
|
||||
// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//*/code' 'impl<T> Sync for \
|
||||
// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//code' 'impl<T> Sync for \
|
||||
// Foo<T> where T: Sync'
|
||||
//
|
||||
// @has - '//*[@id="implementations-list"]/*[@class="impl"]//*/code' \
|
||||
// @has - '//*[@id="implementations-list"]/*[@class="impl"]//code' \
|
||||
// 'impl<T> Send for Foo<T>'
|
||||
//
|
||||
// @count - '//*[@id="implementations-list"]/*[@class="impl"]' 1
|
||||
|
|
|
|||
|
|
@ -3,10 +3,10 @@ pub struct Inner<T: Copy> {
|
|||
}
|
||||
|
||||
// @has negative/struct.Outer.html
|
||||
// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//*/code' "impl<T> !Send for \
|
||||
// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//code' "impl<T> !Send for \
|
||||
// Outer<T>"
|
||||
//
|
||||
// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//*/code' "impl<T> \
|
||||
// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//code' "impl<T> \
|
||||
// !Sync for Outer<T>"
|
||||
pub struct Outer<T: Copy> {
|
||||
inner_field: Inner<T>,
|
||||
|
|
|
|||
|
|
@ -9,10 +9,10 @@ where
|
|||
}
|
||||
|
||||
// @has nested/struct.Foo.html
|
||||
// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//*/code' 'impl<T> Send for \
|
||||
// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//code' 'impl<T> Send for \
|
||||
// Foo<T> where T: Copy'
|
||||
//
|
||||
// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//*/code' \
|
||||
// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//code' \
|
||||
// 'impl<T> Sync for Foo<T> where T: Sync'
|
||||
pub struct Foo<T> {
|
||||
inner_field: Inner<T>,
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ where
|
|||
}
|
||||
|
||||
// @has no_redundancy/struct.Outer.html
|
||||
// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//*/code' "impl<T> Send for \
|
||||
// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//code' "impl<T> Send for \
|
||||
// Outer<T> where T: Copy + Send"
|
||||
pub struct Outer<T> {
|
||||
inner_field: Inner<T>,
|
||||
|
|
|
|||
|
|
@ -23,10 +23,10 @@ where
|
|||
}
|
||||
|
||||
// @has project/struct.Foo.html
|
||||
// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//*/code' "impl<'c, K> Send \
|
||||
// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//code' "impl<'c, K> Send \
|
||||
// for Foo<'c, K> where K: MyTrait<MyItem = bool>, 'c: 'static"
|
||||
//
|
||||
// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//*/code' "impl<'c, K> Sync \
|
||||
// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//code' "impl<'c, K> Sync \
|
||||
// for Foo<'c, K> where K: MyTrait, <K as MyTrait>::MyItem: OtherTrait, 'c: 'static,"
|
||||
pub struct Foo<'c, K: 'c> {
|
||||
inner_field: Inner<'c, K>,
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ impl<T> Pattern for Wrapper<T> {
|
|||
|
||||
|
||||
// @has self_referential/struct.WriteAndThen.html
|
||||
// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//*/code' "impl<P1> Send for \
|
||||
// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//code' "impl<P1> Send for \
|
||||
// WriteAndThen<P1> where <P1 as Pattern>::Value: Send"
|
||||
pub struct WriteAndThen<P1>(pub P1::Value,pub <Constrain<P1, Wrapper<P1::Value>> as Pattern>::Value)
|
||||
where P1: Pattern;
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ pub trait OwnedTrait<'a> {
|
|||
}
|
||||
|
||||
// @has static_region/struct.Owned.html
|
||||
// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//*/code' "impl<T> Send for \
|
||||
// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//code' "impl<T> Send for \
|
||||
// Owned<T> where <T as OwnedTrait<'static>>::Reader: Send"
|
||||
pub struct Owned<T> where T: OwnedTrait<'static> {
|
||||
marker: <T as OwnedTrait<'static>>::Reader,
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@ LL | Enum::EnumStructVariant { x: 1, y: 2, z: 3 }
|
|||
error[E0308]: mismatched types
|
||||
--> $DIR/issue-13624.rs:22:9
|
||||
|
|
||||
LL | match enum_struct_variant {
|
||||
| ------------------- this match expression has type `()`
|
||||
LL | a::Enum::EnumStructVariant { x, y, z } => {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected (), found enum `a::Enum`
|
||||
|
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
error[E0308]: mismatched types
|
||||
--> $DIR/E0308-4.rs:4:9
|
||||
|
|
||||
LL | match x {
|
||||
| - this match expression has type `u8`
|
||||
LL | 0u8..=3i8 => (), //~ ERROR E0308
|
||||
| ^^^^^^^^^ expected u8, found i8
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
error[E0308]: mismatched types
|
||||
--> $DIR/issue-11844.rs:6:9
|
||||
|
|
||||
LL | match a {
|
||||
| - this match expression has type `std::option::Option<std::boxed::Box<{integer}>>`
|
||||
LL | Ok(a) => //~ ERROR: mismatched types
|
||||
| ^^^^^ expected enum `std::option::Option`, found enum `std::result::Result`
|
||||
|
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
error[E0308]: mismatched types
|
||||
--> $DIR/issue-12552.rs:6:5
|
||||
|
|
||||
LL | match t {
|
||||
| - this match expression has type `std::result::Result<_, {integer}>`
|
||||
LL | Some(k) => match k { //~ ERROR mismatched types
|
||||
| ^^^^^^^ expected enum `std::result::Result`, found enum `std::option::Option`
|
||||
|
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
error[E0308]: mismatched types
|
||||
--> $DIR/issue-13466.rs:8:9
|
||||
|
|
||||
LL | let _x: usize = match Some(1) {
|
||||
| ------- this match expression has type `std::option::Option<{integer}>`
|
||||
LL | Ok(u) => u,
|
||||
| ^^^^^ expected enum `std::option::Option`, found enum `std::result::Result`
|
||||
|
|
||||
|
|
@ -10,6 +12,9 @@ LL | Ok(u) => u,
|
|||
error[E0308]: mismatched types
|
||||
--> $DIR/issue-13466.rs:14:9
|
||||
|
|
||||
LL | let _x: usize = match Some(1) {
|
||||
| ------- this match expression has type `std::option::Option<{integer}>`
|
||||
...
|
||||
LL | Err(e) => panic!(e)
|
||||
| ^^^^^^ expected enum `std::option::Option`, found enum `std::result::Result`
|
||||
|
|
||||
|
|
|
|||
|
|
@ -1,6 +1,9 @@
|
|||
error[E0308]: mismatched types
|
||||
--> $DIR/issue-15896.rs:11:11
|
||||
|
|
||||
LL | let u = match e {
|
||||
| - this match expression has type `main::R`
|
||||
LL | E::B(
|
||||
LL | Tau{t: x},
|
||||
| ^^^^^^^^^ expected enum `main::R`, found struct `main::Tau`
|
||||
|
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
error[E0308]: mismatched types
|
||||
--> $DIR/issue-16401.rs:8:9
|
||||
|
|
||||
LL | match () {
|
||||
| -- this match expression has type `()`
|
||||
LL | Slice { data: data, len: len } => (),
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected (), found struct `Slice`
|
||||
|
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
error[E0308]: mismatched types
|
||||
--> $DIR/issue-3680.rs:3:9
|
||||
|
|
||||
LL | match None {
|
||||
| ---- this match expression has type `std::option::Option<_>`
|
||||
LL | Err(_) => ()
|
||||
| ^^^^^^ expected enum `std::option::Option`, found enum `std::result::Result`
|
||||
|
|
||||
|
|
|
|||
|
|
@ -28,6 +28,8 @@ LL | (true, false, false) => ()
|
|||
error[E0308]: mismatched types
|
||||
--> $DIR/issue-5100.rs:33:9
|
||||
|
|
||||
LL | match (true, false) {
|
||||
| ------------- this match expression has type `(bool, bool)`
|
||||
LL | box (true, false) => ()
|
||||
| ^^^^^^^^^^^^^^^^^ expected tuple, found struct `std::boxed::Box`
|
||||
|
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
error[E0308]: mismatched types
|
||||
--> $DIR/issue-5358-1.rs:6:9
|
||||
|
|
||||
LL | match S(Either::Left(5)) {
|
||||
| ------------------ this match expression has type `S`
|
||||
LL | Either::Right(_) => {}
|
||||
| ^^^^^^^^^^^^^^^^ expected struct `S`, found enum `Either`
|
||||
|
|
||||
|
|
|
|||
35
src/test/ui/issues/issue-57472.rs
Normal file
35
src/test/ui/issues/issue-57472.rs
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
#![crate_type="lib"]
|
||||
#![deny(unreachable_patterns)]
|
||||
|
||||
mod test_struct {
|
||||
// Test the exact copy of the minimal example
|
||||
// posted in the issue.
|
||||
pub struct Punned {
|
||||
foo: [u8; 1],
|
||||
bar: [u8; 1],
|
||||
}
|
||||
|
||||
pub fn test(punned: Punned) {
|
||||
match punned {
|
||||
Punned { foo: [_], .. } => println!("foo"),
|
||||
Punned { bar: [_], .. } => println!("bar"),
|
||||
//~^ ERROR unreachable pattern [unreachable_patterns]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mod test_union {
|
||||
// Test the same thing using a union.
|
||||
pub union Punned {
|
||||
foo: [u8; 1],
|
||||
bar: [u8; 1],
|
||||
}
|
||||
|
||||
pub fn test(punned: Punned) {
|
||||
match punned {
|
||||
Punned { foo: [_] } => println!("foo"),
|
||||
Punned { bar: [_] } => println!("bar"),
|
||||
//~^ ERROR unreachable pattern [unreachable_patterns]
|
||||
}
|
||||
}
|
||||
}
|
||||
20
src/test/ui/issues/issue-57472.stderr
Normal file
20
src/test/ui/issues/issue-57472.stderr
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
error: unreachable pattern
|
||||
--> $DIR/issue-57472.rs:15:13
|
||||
|
|
||||
LL | Punned { bar: [_], .. } => println!("bar"),
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: lint level defined here
|
||||
--> $DIR/issue-57472.rs:2:9
|
||||
|
|
||||
LL | #![deny(unreachable_patterns)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: unreachable pattern
|
||||
--> $DIR/issue-57472.rs:31:13
|
||||
|
|
||||
LL | Punned { bar: [_] } => println!("bar"),
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
|
@ -1,6 +1,8 @@
|
|||
error[E0308]: mismatched types
|
||||
--> $DIR/issue-7092.rs:6:9
|
||||
|
|
||||
LL | match x {
|
||||
| - this match expression has type `Whatever`
|
||||
LL | Some(field) =>
|
||||
| ^^^^^^^^^^^ expected enum `Whatever`, found enum `std::option::Option`
|
||||
|
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
error[E0308]: mismatched types
|
||||
--> $DIR/match-struct.rs:6:9
|
||||
|
|
||||
LL | match (S { a: 1 }) {
|
||||
| ------------ this match expression has type `S`
|
||||
LL | E::C(_) => (),
|
||||
| ^^^^^^^ expected struct `S`, found enum `E`
|
||||
|
|
||||
|
|
|
|||
|
|
@ -2,7 +2,9 @@ error[E0308]: mismatched types
|
|||
--> $DIR/match-tag-unary.rs:4:43
|
||||
|
|
||||
LL | fn main() { let x: A = A::A(0); match x { B::B(y) => { } } } //~ ERROR mismatched types
|
||||
| ^^^^^^^ expected enum `A`, found enum `B`
|
||||
| - ^^^^^^^ expected enum `A`, found enum `B`
|
||||
| |
|
||||
| this match expression has type `A`
|
||||
|
|
||||
= note: expected type `A`
|
||||
found type `B`
|
||||
|
|
|
|||
|
|
@ -21,6 +21,8 @@ LL | A::B(_, _, _) => (), //~ ERROR this pattern has 3 fields, but
|
|||
error[E0308]: mismatched types
|
||||
--> $DIR/pattern-error-continue.rs:22:9
|
||||
|
|
||||
LL | match 'c' {
|
||||
| --- this match expression has type `char`
|
||||
LL | S { .. } => (),
|
||||
| ^^^^^^^^ expected char, found struct `S`
|
||||
|
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
error[E0308]: mismatched types
|
||||
--> $DIR/pattern-tyvar.rs:5:18
|
||||
|
|
||||
LL | match t {
|
||||
| - this match expression has type `std::option::Option<std::vec::Vec<isize>>`
|
||||
LL | Bar::T1(_, Some::<isize>(x)) => { //~ ERROR mismatched types
|
||||
| ^^^^^^^^^^^^^^^^ expected struct `std::vec::Vec`, found isize
|
||||
|
|
||||
|
|
|
|||
|
|
@ -109,6 +109,8 @@ LL | PointF::<u32> { .. } => {} //~ ERROR wrong number of type arguments
|
|||
error[E0308]: mismatched types
|
||||
--> $DIR/structure-constructor-type-mismatch.rs:54:9
|
||||
|
|
||||
LL | match (Point { x: 1, y: 2 }) {
|
||||
| ---------------------- this match expression has type `Point<{integer}>`
|
||||
LL | PointF::<u32> { .. } => {} //~ ERROR wrong number of type arguments
|
||||
| ^^^^^^^^^^^^^^^^^^^^ expected integer, found f32
|
||||
|
|
||||
|
|
@ -118,6 +120,8 @@ LL | PointF::<u32> { .. } => {} //~ ERROR wrong number of type arguments
|
|||
error[E0308]: mismatched types
|
||||
--> $DIR/structure-constructor-type-mismatch.rs:59:9
|
||||
|
|
||||
LL | match (Point { x: 1, y: 2 }) {
|
||||
| ---------------------- this match expression has type `Point<{integer}>`
|
||||
LL | PointF { .. } => {} //~ ERROR mismatched types
|
||||
| ^^^^^^^^^^^^^ expected integer, found f32
|
||||
|
|
||||
|
|
@ -127,6 +131,8 @@ LL | PointF { .. } => {} //~ ERROR mismatched types
|
|||
error[E0308]: mismatched types
|
||||
--> $DIR/structure-constructor-type-mismatch.rs:67:9
|
||||
|
|
||||
LL | match (Pair { x: 1, y: 2 }) {
|
||||
| --------------------- this match expression has type `Pair<{integer}, {integer}>`
|
||||
LL | PairF::<u32> { .. } => {} //~ ERROR mismatched types
|
||||
| ^^^^^^^^^^^^^^^^^^^ expected integer, found f32
|
||||
|
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue