Auto merge of #89683 - GuillaumeGomez:rollup-q2mjd9m, r=GuillaumeGomez

Rollup of 6 pull requests

Successful merges:

 - #86506 (Don't normalize xform_ret_ty during method candidate assembly )
 - #89538 (Make rustdoc not highlight `->` and `=>` as operators)
 - #89649 (clippy::complexity fixes)
 - #89668 (Cfg hide more conditions for core and alloc)
 - #89669 (Remove special-casing of never primitive in rustdoc-json-types)
 - #89672 (Remove unwrap_or! macro)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2021-10-08 21:13:27 +00:00
commit f8751436ff
36 changed files with 166 additions and 84 deletions

View File

@ -20,16 +20,6 @@
#[macro_use]
extern crate rustc_macros;
#[macro_export]
macro_rules! unwrap_or {
($opt:expr, $default:expr) => {
match $opt {
Some(x) => x,
None => $default,
}
};
}
pub mod util {
pub mod classify;
pub mod comments;

View File

@ -1345,8 +1345,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
generics
.params
.iter()
.find(|p| def_id == self.resolver.local_def_id(p.id).to_def_id())
.is_some()
.any(|p| def_id == self.resolver.local_def_id(p.id).to_def_id())
}
// Either the `bounded_ty` is not a plain type parameter, or
// it's not found in the generic type parameters list.

View File

@ -201,7 +201,7 @@ impl<'tcx> OutOfScopePrecomputer<'_, 'tcx> {
let bb_data = &self.body[bb];
debug_assert!(hi == bb_data.statements.len());
for &succ_bb in bb_data.terminator().successors() {
if self.visited.insert(succ_bb) == false {
if !self.visited.insert(succ_bb) {
if succ_bb == location.block && first_lo > 0 {
// `succ_bb` has been seen before. If it wasn't
// fully processed, add its first part to `stack`

View File

@ -972,8 +972,7 @@ fn suggest_ampmut<'tcx>(
if let Some(assignment_rhs_span) = opt_assignment_rhs_span {
if let Ok(src) = tcx.sess.source_map().span_to_snippet(assignment_rhs_span) {
let is_mutbl = |ty: &str| -> bool {
if ty.starts_with("mut") {
let rest = &ty[3..];
if let Some(rest) = ty.strip_prefix("mut") {
match rest.chars().next() {
// e.g. `&mut x`
Some(c) if c.is_whitespace() => true,

View File

@ -594,7 +594,7 @@ impl<'a> TraitDef<'a> {
GenericParamKind::Const { ty, kw_span, .. } => {
let const_nodefault_kind = GenericParamKind::Const {
ty: ty.clone(),
kw_span: kw_span.clone(),
kw_span: *kw_span,
// We can't have default values inside impl block
default: None,

View File

@ -130,8 +130,8 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
.tcx()
.sess
.struct_span_err(span, &format!("`impl` associated type signature for `{}` doesn't match `trait` associated type signature", item_name));
err.span_label(impl_sp, &format!("found"));
err.span_label(trait_sp, &format!("expected"));
err.span_label(impl_sp, "found");
err.span_label(trait_sp, "expected");
err.emit();
}

View File

@ -1,7 +1,6 @@
use crate::context::{CheckLintNameResult, LintStore};
use crate::late::unerased_lint_store;
use rustc_ast as ast;
use rustc_ast::unwrap_or;
use rustc_ast_pretty::pprust;
use rustc_data_structures::fx::FxHashMap;
use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder};
@ -233,7 +232,10 @@ impl<'s> LintLevelsBuilder<'s> {
Some(lvl) => lvl,
};
let mut metas = unwrap_or!(attr.meta_item_list(), continue);
let mut metas = match attr.meta_item_list() {
Some(x) => x,
None => continue,
};
if metas.is_empty() {
// FIXME (#55112): issue unused-attributes lint for `#[level()]`

View File

@ -230,8 +230,7 @@ fn check_panic_str<'tcx>(
Err(_) => (None, None),
};
let mut fmt_parser =
Parser::new(fmt.as_ref(), style, snippet.clone(), false, ParseMode::Format);
let mut fmt_parser = Parser::new(fmt, style, snippet.clone(), false, ParseMode::Format);
let n_arguments = (&mut fmt_parser).filter(|a| matches!(a, Piece::NextArgument(_))).count();
if n_arguments > 0 && fmt_parser.errors.is_empty() {

View File

@ -363,7 +363,7 @@ impl Collector<'tcx> {
.collect::<Vec<_>>();
if existing.is_empty() {
// Add if not found
let new_name = passed_lib.new_name.as_ref().map(|s| &**s); // &Option<String> -> Option<&str>
let new_name: Option<&str> = passed_lib.new_name.as_deref();
let lib = NativeLib {
name: Some(Symbol::intern(new_name.unwrap_or(&passed_lib.name))),
kind: passed_lib.kind,

View File

@ -986,7 +986,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
let niche = if def.repr.hide_niche() {
None
} else {
Niche::from_scalar(dl, Size::ZERO, scalar.clone())
Niche::from_scalar(dl, Size::ZERO, *scalar)
};
if let Some(niche) = niche {
match st.largest_niche {
@ -2273,7 +2273,7 @@ where
) -> TyMaybeWithLayout<'tcx> {
let tcx = cx.tcx();
let tag_layout = |tag: Scalar| -> TyAndLayout<'tcx> {
let layout = Layout::scalar(cx, tag.clone());
let layout = Layout::scalar(cx, tag);
TyAndLayout { layout: tcx.intern_layout(layout), ty: tag.value.to_ty(tcx) }
};

View File

@ -130,7 +130,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
TerminatorKind::Call {
func: exchange_malloc,
args: vec![Operand::Move(size), Operand::Move(align)],
destination: Some((Place::from(storage), success)),
destination: Some((storage, success)),
cleanup: None,
from_hir_call: false,
fn_span: expr_span,
@ -153,7 +153,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
}
// Transmute `*mut u8` to the box (thus far, uninitialized):
let box_ = Rvalue::ShallowInitBox(Operand::Move(Place::from(storage)), value.ty);
let box_ = Rvalue::ShallowInitBox(Operand::Move(storage), value.ty);
this.cfg.push_assign(block, source_info, Place::from(result), box_);
// initialize the box contents:

View File

@ -1068,9 +1068,7 @@ impl<'tcx> SplitWildcard<'tcx> {
Missing {
nonexhaustive_enum_missing_real_variants: self
.iter_missing(pcx)
.filter(|c| !c.is_non_exhaustive())
.next()
.is_some(),
.any(|c| !c.is_non_exhaustive()),
}
} else {
Missing { nonexhaustive_enum_missing_real_variants: false }

View File

@ -263,7 +263,7 @@ impl<'a, 'tcx> Helper<'a, 'tcx> {
}
// check that the value being matched on is the same. The
if this_bb_discr_info.targets_with_values.iter().find(|x| x.0 == value).is_none() {
if !this_bb_discr_info.targets_with_values.iter().any(|x| x.0 == value) {
trace!("NO: values being matched on are not the same");
return None;
}

View File

@ -111,8 +111,7 @@ impl<'a, 'tcx> Patcher<'a, 'tcx> {
Operand::Copy(place) | Operand::Move(place) => {
// create new local
let ty = operand.ty(self.local_decls, self.tcx);
let local_decl =
LocalDecl::with_source_info(ty, statement.source_info.clone());
let local_decl = LocalDecl::with_source_info(ty, statement.source_info);
let local = self.local_decls.push(local_decl);
// make it live
let mut make_live_statement = statement.clone();

View File

@ -1767,8 +1767,7 @@ impl CheckAttrVisitor<'tcx> {
fn check_macro_export(&self, hir_id: HirId, attr: &Attribute, target: Target) {
if target != Target::MacroDef {
self.tcx.struct_span_lint_hir(UNUSED_ATTRIBUTES, hir_id, attr.span, |lint| {
lint.build(&format!("`#[macro_export]` only has an effect on macro definitions"))
.emit();
lint.build("`#[macro_export]` only has an effect on macro definitions").emit();
});
}
}

View File

@ -9,7 +9,6 @@ use crate::{BindingKey, ModuleKind, ResolutionError, Resolver, Segment};
use crate::{CrateLint, Module, ModuleOrUniformRoot, ParentScope, PerNS, ScopeSet, Weak};
use crate::{NameBinding, NameBindingKind, PathResult, PrivacyError, ToNameBinding};
use rustc_ast::unwrap_or;
use rustc_ast::NodeId;
use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::ptr_key::PtrKey;
@ -349,10 +348,10 @@ impl<'a> Resolver<'a> {
if !self.is_accessible_from(single_import.vis.get(), parent_scope.module) {
continue;
}
let module = unwrap_or!(
single_import.imported_module.get(),
return Err((Undetermined, Weak::No))
);
let module = match single_import.imported_module.get() {
Some(x) => x,
None => return Err((Undetermined, Weak::No)),
};
let ident = match single_import.kind {
ImportKind::Single { source, .. } => source,
_ => unreachable!(),

View File

@ -278,14 +278,14 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
fn visit_expr(&mut self, expr: &thir::Expr<'tcx>) {
self.is_poly |= expr.ty.definitely_has_param_types_or_consts(self.tcx);
if self.is_poly == false {
if !self.is_poly {
visit::walk_expr(self, expr)
}
}
fn visit_pat(&mut self, pat: &thir::Pat<'tcx>) {
self.is_poly |= pat.ty.definitely_has_param_types_or_consts(self.tcx);
if self.is_poly == false {
if !self.is_poly {
visit::walk_pat(self, pat);
}
}
@ -298,7 +298,7 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
let mut is_poly_vis = IsThirPolymorphic { is_poly: false, thir: body, tcx };
visit::walk_expr(&mut is_poly_vis, &body[body_id]);
debug!("AbstractConstBuilder: is_poly={}", is_poly_vis.is_poly);
if is_poly_vis.is_poly == false {
if !is_poly_vis.is_poly {
return Ok(None);
}

View File

@ -892,7 +892,7 @@ impl<'tcx> TypeVisitor<'tcx> for BoundVarsCollector<'tcx> {
match r {
ty::ReLateBound(index, br) if *index == self.binder_index => match br.kind {
ty::BoundRegionKind::BrNamed(def_id, _name) => {
if self.named_parameters.iter().find(|d| **d == def_id).is_none() {
if !self.named_parameters.iter().any(|d| *d == def_id) {
self.named_parameters.push(def_id);
}
}

View File

@ -329,7 +329,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let obligation = Obligation::new(
ObligationCause::dummy_with_span(callee_expr.span),
self.param_env,
predicate.clone(),
*predicate,
);
let result = self.infcx.evaluate_obligation(&obligation);
self.tcx

View File

@ -753,17 +753,27 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
let (impl_ty, impl_substs) = self.impl_ty_and_substs(impl_def_id);
let impl_ty = impl_ty.subst(self.tcx, impl_substs);
debug!("impl_ty: {:?}", impl_ty);
// Determine the receiver type that the method itself expects.
let xform_tys = self.xform_self_ty(&item, impl_ty, impl_substs);
let (xform_self_ty, xform_ret_ty) = self.xform_self_ty(&item, impl_ty, impl_substs);
debug!("xform_self_ty: {:?}, xform_ret_ty: {:?}", xform_self_ty, xform_ret_ty);
// We can't use normalize_associated_types_in as it will pollute the
// fcx's fulfillment context after this probe is over.
// Note: we only normalize `xform_self_ty` here since the normalization
// of the return type can lead to inference results that prohibit
// valid canidates from being found, see issue #85671
// FIXME Postponing the normalization of the return type likely only hides a deeper bug,
// which might be caused by the `param_env` itself. The clauses of the `param_env`
// maybe shouldn't include `Param`s, but rather fresh variables or be canonicalized,
// see isssue #89650
let cause = traits::ObligationCause::misc(self.span, self.body_id);
let selcx = &mut traits::SelectionContext::new(self.fcx);
let traits::Normalized { value: (xform_self_ty, xform_ret_ty), obligations } =
traits::normalize(selcx, self.param_env, cause, xform_tys);
let traits::Normalized { value: xform_self_ty, obligations } =
traits::normalize(selcx, self.param_env, cause, xform_self_ty);
debug!(
"assemble_inherent_impl_probe: xform_self_ty = {:?}/{:?}",
"assemble_inherent_impl_probe after normalization: xform_self_ty = {:?}/{:?}",
xform_self_ty, xform_ret_ty
);
@ -1420,6 +1430,9 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
};
let mut result = ProbeResult::Match;
let mut xform_ret_ty = probe.xform_ret_ty;
debug!(?xform_ret_ty);
let selcx = &mut traits::SelectionContext::new(self);
let cause = traits::ObligationCause::misc(self.span, self.body_id);
@ -1428,7 +1441,17 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
// match as well (or at least may match, sometimes we
// don't have enough information to fully evaluate).
match probe.kind {
InherentImplCandidate(substs, ref ref_obligations) => {
InherentImplCandidate(ref substs, ref ref_obligations) => {
// `xform_ret_ty` hasn't been normalized yet, only `xform_self_ty`,
// see the reasons mentioned in the comments in `assemble_inherent_impl_probe`
// for why this is necessary
let traits::Normalized {
value: normalized_xform_ret_ty,
obligations: normalization_obligations,
} = traits::normalize(selcx, self.param_env, cause.clone(), probe.xform_ret_ty);
xform_ret_ty = normalized_xform_ret_ty;
debug!("xform_ret_ty after normalization: {:?}", xform_ret_ty);
// Check whether the impl imposes obligations we have to worry about.
let impl_def_id = probe.item.container.id();
let impl_bounds = self.tcx.predicates_of(impl_def_id);
@ -1442,7 +1465,9 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
let candidate_obligations = impl_obligations
.chain(norm_obligations.into_iter())
.chain(ref_obligations.iter().cloned());
.chain(ref_obligations.iter().cloned())
.chain(normalization_obligations.into_iter());
// Evaluate those obligations to see if they might possibly hold.
for o in candidate_obligations {
let o = self.resolve_vars_if_possible(o);
@ -1527,9 +1552,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
}
if let ProbeResult::Match = result {
if let (Some(return_ty), Some(xform_ret_ty)) =
(self.return_type, probe.xform_ret_ty)
{
if let (Some(return_ty), Some(xform_ret_ty)) = (self.return_type, xform_ret_ty) {
let xform_ret_ty = self.resolve_vars_if_possible(xform_ret_ty);
debug!(
"comparing return_ty {:?} with xform ret ty {:?}",
@ -1669,6 +1692,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
self.static_candidates.push(source);
}
#[instrument(level = "debug", skip(self))]
fn xform_self_ty(
&self,
item: &ty::AssocItem,
@ -1683,9 +1707,10 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
}
}
#[instrument(level = "debug", skip(self))]
fn xform_method_sig(&self, method: DefId, substs: SubstsRef<'tcx>) -> ty::FnSig<'tcx> {
let fn_sig = self.tcx.fn_sig(method);
debug!("xform_self_ty(fn_sig={:?}, substs={:?})", fn_sig, substs);
debug!(?fn_sig);
assert!(!substs.has_escaping_bound_vars());

View File

@ -413,7 +413,7 @@ impl<'a, 'tcx> Visitor<'tcx> for RegionCtxt<'a, 'tcx> {
}
hir::ExprKind::Match(ref discr, arms, _) => {
self.link_match(discr, &arms[..]);
self.link_match(discr, arms);
intravisit::walk_expr(self, expr);
}

View File

@ -69,7 +69,12 @@
)]
#![cfg_attr(
not(bootstrap),
doc(cfg_hide(not(test), not(any(test, bootstrap)), target_has_atomic = "ptr"))
doc(cfg_hide(
not(test),
not(any(test, bootstrap)),
any(not(feature = "miri-test-libstd"), test, doctest),
target_has_atomic = "ptr"
))
)]
#![no_std]
#![needs_allocator]

View File

@ -64,6 +64,7 @@
not(bootstrap),
doc(cfg_hide(
not(test),
any(not(feature = "miri-test-libstd"), test, doctest),
target_pointer_width = "16",
target_pointer_width = "32",
target_pointer_width = "64",

View File

@ -435,7 +435,27 @@ impl<'a> Classifier<'a> {
_ => Class::RefKeyWord,
},
// Operators.
// These can either be operators, or arrows.
TokenKind::Eq => match lookahead {
Some(TokenKind::Eq) => {
self.next();
sink(Highlight::Token { text: "==", class: Some(Class::Op) });
return;
}
Some(TokenKind::Gt) => {
self.next();
sink(Highlight::Token { text: "=>", class: None });
return;
}
_ => Class::Op,
},
TokenKind::Minus if lookahead == Some(TokenKind::Gt) => {
self.next();
sink(Highlight::Token { text: "->", class: None });
return;
}
// Other operators.
TokenKind::Minus
| TokenKind::Plus
| TokenKind::Or
@ -443,7 +463,6 @@ impl<'a> Classifier<'a> {
| TokenKind::Caret
| TokenKind::Percent
| TokenKind::Bang
| TokenKind::Eq
| TokenKind::Lt
| TokenKind::Gt => Class::Op,

View File

@ -13,7 +13,7 @@
<span class="kw">use</span> <span class="ident">std::path</span>::{<span class="ident">Path</span>, <span class="ident">PathBuf</span>};
<span class="attribute">#[<span class="ident">cfg</span>(<span class="ident">target_os</span> <span class="op">=</span> <span class="string">&quot;linux&quot;</span>)]</span>
<span class="kw">fn</span> <span class="ident">main</span>() {
<span class="kw">fn</span> <span class="ident">main</span>() -&gt; () {
<span class="kw">let</span> <span class="ident">foo</span> <span class="op">=</span> <span class="bool-val">true</span> <span class="op">&amp;&amp;</span> <span class="bool-val">false</span> <span class="op">|</span><span class="op">|</span> <span class="bool-val">true</span>;
<span class="kw">let</span> <span class="kw">_</span>: <span class="kw-2">*</span><span class="kw">const</span> () <span class="op">=</span> <span class="number">0</span>;
<span class="kw">let</span> <span class="kw">_</span> <span class="op">=</span> <span class="kw-2">&amp;</span><span class="ident">foo</span>;
@ -27,11 +27,11 @@
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">s</span> <span class="op">=</span> <span class="ident">String::new</span>();
<span class="kw">match</span> <span class="kw-2">&amp;</span><span class="ident">s</span> {
<span class="kw-2">ref</span> <span class="kw-2">mut</span> <span class="ident">x</span> <span class="op">=</span><span class="op">&gt;</span> {}
<span class="kw-2">ref</span> <span class="kw-2">mut</span> <span class="ident">x</span> =&gt; {}
}
}
<span class="macro">macro_rules!</span> <span class="ident">bar</span> {
(<span class="macro-nonterminal">$</span><span class="macro-nonterminal">foo</span>:<span class="ident">tt</span>) <span class="op">=</span><span class="op">&gt;</span> {};
(<span class="macro-nonterminal">$</span><span class="macro-nonterminal">foo</span>:<span class="ident">tt</span>) =&gt; {};
}
</code></pre>

View File

@ -3,7 +3,7 @@
use std::path::{Path, PathBuf};
#[cfg(target_os = "linux")]
fn main() {
fn main() -> () {
let foo = true && false || true;
let _: *const () = 0;
let _ = &foo;

View File

@ -418,7 +418,6 @@ impl FromWithTcx<clean::Type> for Type {
}
}
Generic(s) => Type::Generic(s.to_string()),
Primitive(clean::PrimitiveType::Never) => Type::Never,
Primitive(p) => Type::Primitive(p.as_sym().to_string()),
BareFunction(f) => Type::FunctionPointer(Box::new((*f).into_tcx(tcx))),
Tuple(t) => Type::Tuple(t.into_iter().map(|x| x.into_tcx(tcx)).collect()),

View File

@ -207,7 +207,7 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
debug!("Done with crate");
for primitive in Rc::clone(&self.cache).primitive_locations.values() {
self.get_impls(primitive.clone());
self.get_impls(*primitive);
}
let mut index = (*self.index).clone().into_inner();
@ -255,7 +255,7 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
)
})
.collect(),
format_version: 8,
format_version: 9,
};
let mut p = self.out_path.clone();
p.push(output.index.get(&output.root).unwrap().name.clone().unwrap());

View File

@ -388,8 +388,6 @@ pub enum Type {
},
/// `impl TraitA + TraitB + ...`
ImplTrait(Vec<GenericBound>),
/// `!`
Never,
/// `_`
Infer,
/// `*mut u32`, `*u8`, etc.

View File

@ -0,0 +1,22 @@
#![feature(never_type)]
// @has primitives.json "$.index[*][?(@.name=='PrimNever')].visibility" \"public\"
// @has - "$.index[*][?(@.name=='PrimNever')].inner.type.kind" \"primitive\"
// @has - "$.index[*][?(@.name=='PrimNever')].inner.type.inner" \"never\"
pub type PrimNever = !;
// @has - "$.index[*][?(@.name=='PrimStr')].inner.type.kind" \"primitive\"
// @has - "$.index[*][?(@.name=='PrimStr')].inner.type.inner" \"str\"
pub type PrimStr = str;
// @has - "$.index[*][?(@.name=='PrimBool')].inner.type.kind" \"primitive\"
// @has - "$.index[*][?(@.name=='PrimBool')].inner.type.inner" \"bool\"
pub type PrimBool = bool;
// @has - "$.index[*][?(@.name=='PrimChar')].inner.type.kind" \"primitive\"
// @has - "$.index[*][?(@.name=='PrimChar')].inner.type.inner" \"char\"
pub type PrimChar = char;
// @has - "$.index[*][?(@.name=='PrimU8')].inner.type.kind" \"primitive\"
// @has - "$.index[*][?(@.name=='PrimU8')].inner.type.inner" \"u8\"
pub type PrimU8 = u8;

View File

@ -6,37 +6,31 @@
// @has 'foo/macro.todo.html'
// @has - '//span[@class="macro"]' 'macro_rules!'
// @has - '//span[@class="ident"]' 'todo'
// Note: count = 2 * ('=' + '>') + '+' = 2 * (1 + 1) + 1 = 5
// @count - '//pre[@class="rust macro"]//span[@class="op"]' 5
// Note: the only op is the `+`
// @count - '//pre[@class="rust macro"]//span[@class="op"]' 1
// @has - '{ ()'
// @has - '//span[@class="op"]' '='
// @has - '//span[@class="op"]' '>'
// @has - '{ ... };'
// @has - '($('
// @has - '{ () =&gt; { ... }; ($('
// @has - '//span[@class="macro-nonterminal"]' '$'
// @has - '//span[@class="macro-nonterminal"]' 'arg'
// @has - ':'
// @has - '//span[@class="ident"]' 'tt'
// @has - '),'
// @has - '//span[@class="op"]' '+'
// @has - ')'
// @has - ') =&gt; { ... }; }'
pub use std::todo;
mod mod1 {
// @has 'foo/macro.macro1.html'
// @has - 'macro_rules!'
// @has - 'macro1'
// @has - '{ ()'
// @has - '($('
// @has - '{ () =&gt; { ... }; ($('
// @has - '//span[@class="macro-nonterminal"]' '$'
// @has - '//span[@class="macro-nonterminal"]' 'arg'
// @has - ':'
// @has - 'expr'
// @has - '),'
// @has - '+'
// @has - ')'
// @has - ') =&gt; { ... }; }'
#[macro_export]
macro_rules! macro1 {
() => {};

View File

@ -6,7 +6,6 @@ LL | let _result = &Some(42).as_deref();
|
= note: the following trait bounds were not satisfied:
`{integer}: Deref`
`<{integer} as Deref>::Target = _`
error: aborting due to previous error

View File

@ -6,7 +6,7 @@ LL | let _result = &mut Some(42).as_deref_mut();
|
= note: the following trait bounds were not satisfied:
`{integer}: DerefMut`
`<{integer} as Deref>::Target = _`
`{integer}: Deref`
error: aborting due to previous error

View File

@ -6,7 +6,6 @@ LL | let _result = &Ok(42).as_deref();
|
= note: the following trait bounds were not satisfied:
`{integer}: Deref`
`<{integer} as Deref>::Target = _`
error: aborting due to previous error

View File

@ -6,7 +6,7 @@ LL | let _result = &mut Ok(42).as_deref_mut();
|
= note: the following trait bounds were not satisfied:
`{integer}: DerefMut`
`<{integer} as Deref>::Target = _`
`{integer}: Deref`
error: aborting due to previous error

View File

@ -0,0 +1,37 @@
// check-pass
// Some trait with a function that returns a slice:
pub trait AsSlice {
type Element;
fn as_slice(&self) -> &[Self::Element];
}
// Some type
pub struct A<Cont>(Cont);
// Here we say that if A wraps a slice, then it implements AsSlice
impl<'a, Element> AsSlice for A<&'a [Element]> {
type Element = Element;
fn as_slice(&self) -> &[Self::Element] {
self.0
}
}
impl<Cont> A<Cont> {
// We want this function to work
pub fn failing<Coef>(&self)
where
Self: AsSlice<Element = Coef>,
{
self.as_ref_a().as_ref_a();
}
pub fn as_ref_a<Coef>(&self) -> A<&[<Self as AsSlice>::Element]>
where
Self: AsSlice<Element = Coef>,
{
A(self.as_slice())
}
}
fn main() {}