Auto merge of #116605 - GuillaumeGomez:rollup-12ba2o6, r=GuillaumeGomez

Rollup of 7 pull requests

Successful merges:

 - #109422 (rustdoc-search: add impl disambiguator to duplicate assoc items)
 - #116250 (On type error of closure call argument, point at earlier calls that affected inference)
 - #116444 (add test for const-eval error in dead code during monomorphization)
 - #116503 (Update docs for mips target tier demotion.)
 - #116559 (Mark `new_in` as `const` for BTree collections)
 - #116560 (In smir use `FxIndexMap` to store indexed ids)
 - #116574 (Update books)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2023-10-10 17:37:15 +00:00
commit c30b28bdc1
38 changed files with 700 additions and 109 deletions

View file

@ -4504,6 +4504,7 @@ dependencies = [
name = "rustc_smir"
version = "0.0.0"
dependencies = [
"rustc_data_structures",
"rustc_driver",
"rustc_hir",
"rustc_interface",

View file

@ -229,6 +229,7 @@ Compatibility Notes
this should only impact users of other registries, or people who don't publish
to a registry.
[#12291](https://github.com/rust-lang/cargo/pull/12291)
- [Demoted `mips*-unknown-linux-gnu*` targets from host tier 2 to target tier 3 support.](https://github.com/rust-lang/rust/pull/113274)
Version 1.71.1 (2023-08-03)
===========================

View file

@ -16,6 +16,7 @@ use rustc_errors::{
use rustc_hir as hir;
use rustc_hir::def::{CtorOf, DefKind, Res};
use rustc_hir::def_id::DefId;
use rustc_hir::intravisit::Visitor;
use rustc_hir::{ExprKind, Node, QPath};
use rustc_hir_analysis::astconv::AstConv;
use rustc_hir_analysis::check::intrinsicck::InlineAsmCtxt;
@ -28,7 +29,7 @@ use rustc_infer::infer::TypeTrace;
use rustc_infer::infer::{DefineOpaqueTypes, InferOk};
use rustc_middle::ty::adjustment::AllowTwoPhase;
use rustc_middle::ty::visit::TypeVisitableExt;
use rustc_middle::ty::{self, IsSuggestable, Ty};
use rustc_middle::ty::{self, IsSuggestable, Ty, TyCtxt};
use rustc_session::Session;
use rustc_span::symbol::{kw, Ident};
use rustc_span::{self, sym, BytePos, Span};
@ -722,6 +723,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
&mut err,
fn_def_id,
callee_ty,
call_expr,
None,
Some(mismatch_idx),
is_method,
);
@ -826,6 +829,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
&mut err,
fn_def_id,
callee_ty,
call_expr,
Some(expected_ty),
Some(expected_idx.as_usize()),
is_method,
);
@ -1208,7 +1213,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
// Call out where the function is defined
self.label_fn_like(&mut err, fn_def_id, callee_ty, None, is_method);
self.label_fn_like(&mut err, fn_def_id, callee_ty, call_expr, None, None, is_method);
// And add a suggestion block for all of the parameters
let suggestion_text = match suggestion_text {
@ -1899,6 +1904,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
err: &mut Diagnostic,
callable_def_id: Option<DefId>,
callee_ty: Option<Ty<'tcx>>,
call_expr: &'tcx hir::Expr<'tcx>,
expected_ty: Option<Ty<'tcx>>,
// A specific argument should be labeled, instead of all of them
expected_idx: Option<usize>,
is_method: bool,
@ -2015,6 +2022,46 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let param = expected_idx
.and_then(|expected_idx| self.tcx.hir().body(*body).params.get(expected_idx));
let (kind, span) = if let Some(param) = param {
// Try to find earlier invocations of this closure to find if the type mismatch
// is because of inference. If we find one, point at them.
let mut call_finder = FindClosureArg { tcx: self.tcx, calls: vec![] };
let node = self.tcx
.opt_local_def_id_to_hir_id(self.tcx.hir().get_parent_item(call_expr.hir_id))
.and_then(|hir_id| self.tcx.hir().find(hir_id));
match node {
Some(hir::Node::Item(item)) => call_finder.visit_item(item),
Some(hir::Node::TraitItem(item)) => call_finder.visit_trait_item(item),
Some(hir::Node::ImplItem(item)) => call_finder.visit_impl_item(item),
_ => {}
}
let typeck = self.typeck_results.borrow();
for (rcvr, args) in call_finder.calls {
if let Some(rcvr_ty) = typeck.node_type_opt(rcvr.hir_id)
&& let ty::Closure(call_def_id, _) = rcvr_ty.kind()
&& def_id == *call_def_id
&& let Some(idx) = expected_idx
&& let Some(arg) = args.get(idx)
&& let Some(arg_ty) = typeck.node_type_opt(arg.hir_id)
&& let Some(expected_ty) = expected_ty
&& self.can_eq(self.param_env, arg_ty, expected_ty)
{
let mut sp: MultiSpan = vec![arg.span].into();
sp.push_span_label(
arg.span,
format!("expected because this argument is of type `{arg_ty}`"),
);
sp.push_span_label(rcvr.span, "in this closure call");
err.span_note(
sp,
format!(
"expected because the closure was earlier called with an \
argument of type `{arg_ty}`",
),
);
break;
}
}
("closure parameter", param.span)
} else {
("closure", self.tcx.def_span(def_id))
@ -2028,3 +2075,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
}
}
struct FindClosureArg<'tcx> {
tcx: TyCtxt<'tcx>,
calls: Vec<(&'tcx hir::Expr<'tcx>, &'tcx [hir::Expr<'tcx>])>,
}
impl<'tcx> Visitor<'tcx> for FindClosureArg<'tcx> {
type NestedFilter = rustc_middle::hir::nested_filter::All;
fn nested_visit_map(&mut self) -> Self::Map {
self.tcx.hir()
}
fn visit_expr(&mut self, ex: &'tcx hir::Expr<'tcx>) {
if let hir::ExprKind::Call(rcvr, args) = ex.kind {
self.calls.push((rcvr, args));
}
hir::intravisit::walk_expr(self, ex);
}
}

View file

@ -4,6 +4,7 @@ version = "0.0.0"
edition = "2021"
[dependencies]
rustc_data_structures = { path = "../rustc_data_structures" }
rustc_driver = { path = "../rustc_driver" }
rustc_hir = { path = "../rustc_hir" }
rustc_interface = { path = "../rustc_interface" }

View file

@ -3,24 +3,27 @@
//! For that, we define APIs that will temporarily be public to 3P that exposes rustc internal APIs
//! until stable MIR is complete.
use std::ops::{ControlFlow, Index};
use crate::rustc_internal;
use crate::rustc_smir::Tables;
use rustc_data_structures::fx;
use rustc_driver::{Callbacks, Compilation, RunCompiler};
use rustc_interface::{interface, Queries};
use rustc_middle::mir::interpret::AllocId;
use rustc_middle::ty::TyCtxt;
use rustc_span::def_id::{CrateNum, DefId};
use rustc_span::Span;
use stable_mir::ty::IndexedVal;
use stable_mir::CompilerError;
use std::fmt::Debug;
use std::hash::Hash;
use std::ops::{ControlFlow, Index};
impl<'tcx> Index<stable_mir::DefId> for Tables<'tcx> {
type Output = DefId;
#[inline(always)]
fn index(&self, index: stable_mir::DefId) -> &Self::Output {
&self.def_ids[index.0]
&self.def_ids[index]
}
}
@ -29,7 +32,7 @@ impl<'tcx> Index<stable_mir::ty::Span> for Tables<'tcx> {
#[inline(always)]
fn index(&self, index: stable_mir::ty::Span) -> &Self::Output {
&self.spans[index.0]
&self.spans[index]
}
}
@ -95,36 +98,15 @@ impl<'tcx> Tables<'tcx> {
}
fn create_def_id(&mut self, did: DefId) -> stable_mir::DefId {
// FIXME: this becomes inefficient when we have too many ids
for (i, &d) in self.def_ids.iter().enumerate() {
if d == did {
return stable_mir::DefId(i);
}
}
let id = self.def_ids.len();
self.def_ids.push(did);
stable_mir::DefId(id)
self.def_ids.create_or_fetch(did)
}
fn create_alloc_id(&mut self, aid: AllocId) -> stable_mir::AllocId {
// FIXME: this becomes inefficient when we have too many ids
if let Some(i) = self.alloc_ids.iter().position(|a| *a == aid) {
return stable_mir::AllocId(i);
};
let id = self.def_ids.len();
self.alloc_ids.push(aid);
stable_mir::AllocId(id)
self.alloc_ids.create_or_fetch(aid)
}
pub(crate) fn create_span(&mut self, span: Span) -> stable_mir::ty::Span {
for (i, &sp) in self.spans.iter().enumerate() {
if sp == span {
return stable_mir::ty::Span(i);
}
}
let id = self.spans.len();
self.spans.push(span);
stable_mir::ty::Span(id)
self.spans.create_or_fetch(span)
}
}
@ -134,7 +116,13 @@ pub fn crate_num(item: &stable_mir::Crate) -> CrateNum {
pub fn run(tcx: TyCtxt<'_>, f: impl FnOnce()) {
stable_mir::run(
Tables { tcx, def_ids: vec![], alloc_ids: vec![], spans: vec![], types: vec![] },
Tables {
tcx,
def_ids: rustc_internal::IndexMap { index_map: fx::FxIndexMap::default() },
alloc_ids: rustc_internal::IndexMap { index_map: fx::FxIndexMap::default() },
spans: rustc_internal::IndexMap { index_map: fx::FxIndexMap::default() },
types: vec![],
},
f,
);
}
@ -197,3 +185,29 @@ where
})
}
}
/// Simmilar to rustc's `FxIndexMap`, `IndexMap` with extra
/// safety features added.
pub struct IndexMap<K, V> {
index_map: fx::FxIndexMap<K, V>,
}
impl<K: PartialEq + Hash + Eq, V: Copy + Debug + PartialEq + IndexedVal> IndexMap<K, V> {
pub fn create_or_fetch(&mut self, key: K) -> V {
let len = self.index_map.len();
let v = self.index_map.entry(key).or_insert(V::to_val(len));
*v
}
}
impl<K: PartialEq + Hash + Eq, V: Copy + Debug + PartialEq + IndexedVal> Index<V>
for IndexMap<K, V>
{
type Output = K;
fn index(&self, index: V) -> &Self::Output {
let (k, v) = self.index_map.get_index(index.to_index()).unwrap();
assert_eq!(*v, index, "Provided value doesn't match with indexed value");
k
}
}

View file

@ -7,6 +7,7 @@
//!
//! For now, we are developing everything inside `rustc`, thus, we keep this module private.
use crate::rustc_internal::IndexMap;
use crate::rustc_smir::hir::def::DefKind;
use crate::rustc_smir::stable_mir::ty::{BoundRegion, EarlyBoundRegion, Region};
use rustc_hir as hir;
@ -201,9 +202,9 @@ impl<S, R: PartialEq> PartialEq<R> for MaybeStable<S, R> {
pub struct Tables<'tcx> {
pub tcx: TyCtxt<'tcx>,
pub def_ids: Vec<DefId>,
pub alloc_ids: Vec<AllocId>,
pub spans: Vec<rustc_span::Span>,
pub def_ids: IndexMap<DefId, stable_mir::DefId>,
pub alloc_ids: IndexMap<AllocId, stable_mir::AllocId>,
pub spans: IndexMap<rustc_span::Span, Span>,
pub types: Vec<MaybeStable<stable_mir::ty::TyKind, Ty<'tcx>>>,
}

View file

@ -22,7 +22,8 @@ use std::fmt;
use std::fmt::Debug;
use self::ty::{
GenericPredicates, Generics, ImplDef, ImplTrait, Span, TraitDecl, TraitDef, Ty, TyKind,
GenericPredicates, Generics, ImplDef, ImplTrait, IndexedVal, Span, TraitDecl, TraitDef, Ty,
TyKind,
};
#[macro_use]
@ -41,7 +42,7 @@ pub type CrateNum = usize;
/// A unique identification number for each item accessible for the current compilation unit.
#[derive(Clone, Copy, PartialEq, Eq)]
pub struct DefId(pub usize);
pub struct DefId(usize);
impl Debug for DefId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
@ -52,9 +53,28 @@ impl Debug for DefId {
}
}
impl IndexedVal for DefId {
fn to_val(index: usize) -> Self {
DefId(index)
}
fn to_index(&self) -> usize {
self.0
}
}
/// A unique identification number for each provenance
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub struct AllocId(pub usize);
pub struct AllocId(usize);
impl IndexedVal for AllocId {
fn to_val(index: usize) -> Self {
AllocId(index)
}
fn to_index(&self) -> usize {
self.0
}
}
/// A list of crate items.
pub type CrateItems = Vec<CrateItem>;

View file

@ -75,7 +75,7 @@ pub struct Placeholder<T> {
}
#[derive(Clone, Copy, PartialEq, Eq)]
pub struct Span(pub usize);
pub struct Span(usize);
impl Debug for Span {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
@ -86,6 +86,15 @@ impl Debug for Span {
}
}
impl IndexedVal for Span {
fn to_val(index: usize) -> Self {
Span(index)
}
fn to_index(&self) -> usize {
self.0
}
}
#[derive(Clone, Debug)]
pub enum TyKind {
RigidTy(RigidTy),
@ -565,3 +574,9 @@ pub enum ImplPolarity {
Negative,
Reservation,
}
pub trait IndexedVal {
fn to_val(index: usize) -> Self;
fn to_index(&self) -> usize;
}

View file

@ -669,7 +669,7 @@ impl<K, V, A: Allocator + Clone> BTreeMap<K, V, A> {
/// map.insert(1, "a");
/// ```
#[unstable(feature = "btreemap_alloc", issue = "32838")]
pub fn new_in(alloc: A) -> BTreeMap<K, V, A> {
pub const fn new_in(alloc: A) -> BTreeMap<K, V, A> {
BTreeMap { root: None, length: 0, alloc: ManuallyDrop::new(alloc), _marker: PhantomData }
}
}

View file

@ -358,7 +358,7 @@ impl<T, A: Allocator + Clone> BTreeSet<T, A> {
/// let mut set: BTreeSet<i32> = BTreeSet::new_in(Global);
/// ```
#[unstable(feature = "btreemap_alloc", issue = "32838")]
pub fn new_in(alloc: A) -> BTreeSet<T, A> {
pub const fn new_in(alloc: A) -> BTreeSet<T, A> {
BTreeSet { map: BTreeMap::new_in(alloc) }
}

@ -1 +1 @@
Subproject commit 5262e1c3b43a2c489df8f6717683a44c7a2260fd
Subproject commit 142b2ed77d33f37a9973772bd95e6144ed9dce43

@ -1 +1 @@
Subproject commit c954202c1e1720cba5628f99543cc01188c7d6fc
Subproject commit 8eb3a01ab74c567b7174784892fb807f2c632d6b

@ -1 +1 @@
Subproject commit a13b7c28ed705891c681ce5417b3d1cdb12cecd1
Subproject commit b98af7d661e4744baab81fb8dc7a049e44a4a998

View file

@ -286,6 +286,10 @@ target | std | host | notes
`mipsel-unknown-linux-musl` | ✓ | | MIPS (little endian) Linux with musl libc
`mipsel-sony-psp` | * | | MIPS (LE) Sony PlayStation Portable (PSP)
[`mipsel-sony-psx`](platform-support/mipsel-sony-psx.md) | * | | MIPS (LE) Sony PlayStation 1 (PSX)
`mips-unknown-linux-gnu` | MIPS Linux (kernel 4.4, glibc 2.23)
`mips64-unknown-linux-gnuabi64` | MIPS64 Linux, n64 ABI (kernel 4.4, glibc 2.23)
`mips64el-unknown-linux-gnuabi64` | MIPS64 (LE) Linux, n64 ABI (kernel 4.4, glibc 2.23)
`mipsel-unknown-linux-gnu` | MIPS (LE) Linux (kernel 4.4, glibc 2.23)
`mipsel-unknown-linux-uclibc` | ✓ | | MIPS (LE) Linux with uClibc
`mipsel-unknown-none` | * | | Bare MIPS (LE) softfloat
[`mipsisa32r6-unknown-linux-gnu`](platform-support/mips-release-6.md) | ? | | 32-bit MIPS Release 6 Big Endian

View file

@ -223,17 +223,16 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> {
// If the impl is from a masked crate or references something from a
// masked crate then remove it completely.
if let clean::ImplItem(ref i) = *item.kind {
if self.cache.masked_crates.contains(&item.item_id.krate())
if let clean::ImplItem(ref i) = *item.kind &&
(self.cache.masked_crates.contains(&item.item_id.krate())
|| i.trait_
.as_ref()
.map_or(false, |t| self.cache.masked_crates.contains(&t.def_id().krate))
|| i.for_
.def_id(self.cache)
.map_or(false, |d| self.cache.masked_crates.contains(&d.krate))
{
return None;
}
.map_or(false, |d| self.cache.masked_crates.contains(&d.krate)))
{
return None;
}
// Propagate a trait method's documentation to all implementors of the
@ -334,33 +333,37 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> {
// A crate has a module at its root, containing all items,
// which should not be indexed. The crate-item itself is
// inserted later on when serializing the search-index.
if item.item_id.as_def_id().map_or(false, |idx| !idx.is_crate_root()) {
if item.item_id.as_def_id().map_or(false, |idx| !idx.is_crate_root())
&& let ty = item.type_()
&& (ty != ItemType::StructField
|| u16::from_str_radix(s.as_str(), 10).is_err())
{
let desc =
short_markdown_summary(&item.doc_value(), &item.link_names(self.cache));
let ty = item.type_();
if ty != ItemType::StructField
|| u16::from_str_radix(s.as_str(), 10).is_err()
{
// In case this is a field from a tuple struct, we don't add it into
// the search index because its name is something like "0", which is
// not useful for rustdoc search.
self.cache.search_index.push(IndexItem {
ty,
name: s,
path: join_with_double_colon(path),
desc,
parent,
parent_idx: None,
search_type: get_function_type_for_search(
&item,
self.tcx,
clean_impl_generics(self.cache.parent_stack.last()).as_ref(),
self.cache,
),
aliases: item.attrs.get_doc_aliases(),
deprecation: item.deprecation(self.tcx),
});
}
// In case this is a field from a tuple struct, we don't add it into
// the search index because its name is something like "0", which is
// not useful for rustdoc search.
self.cache.search_index.push(IndexItem {
ty,
name: s,
path: join_with_double_colon(path),
desc,
parent,
parent_idx: None,
impl_id: if let Some(ParentStackItem::Impl { item_id, .. }) = self.cache.parent_stack.last() {
item_id.as_def_id()
} else {
None
},
search_type: get_function_type_for_search(
&item,
self.tcx,
clean_impl_generics(self.cache.parent_stack.last()).as_ref(),
self.cache,
),
aliases: item.attrs.get_doc_aliases(),
deprecation: item.deprecation(self.tcx),
});
}
}
(Some(parent), None) if is_inherent_impl_item => {
@ -371,6 +374,13 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> {
parent,
item: item.clone(),
impl_generics,
impl_id: if let Some(ParentStackItem::Impl { item_id, .. }) =
self.cache.parent_stack.last()
{
item_id.as_def_id()
} else {
None
},
});
}
_ => {}
@ -541,6 +551,7 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> {
pub(crate) struct OrphanImplItem {
pub(crate) parent: DefId,
pub(crate) impl_id: Option<DefId>,
pub(crate) item: clean::Item,
pub(crate) impl_generics: Option<(clean::Type, clean::Generics)>,
}

View file

@ -54,7 +54,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_hir::def_id::{DefId, DefIdSet};
use rustc_hir::Mutability;
use rustc_middle::middle::stability;
use rustc_middle::ty::TyCtxt;
use rustc_middle::ty::{self, TyCtxt};
use rustc_span::{
symbol::{sym, Symbol},
BytePos, FileName, RealFileName,
@ -102,6 +102,7 @@ pub(crate) struct IndexItem {
pub(crate) desc: String,
pub(crate) parent: Option<DefId>,
pub(crate) parent_idx: Option<isize>,
pub(crate) impl_id: Option<DefId>,
pub(crate) search_type: Option<IndexItemFunctionType>,
pub(crate) aliases: Box<[Symbol]>,
pub(crate) deprecation: Option<Deprecation>,
@ -1877,7 +1878,7 @@ pub(crate) fn render_impl_summary(
aliases: &[String],
) {
let inner_impl = i.inner_impl();
let id = cx.derive_id(get_id_for_impl(&inner_impl.for_, inner_impl.trait_.as_ref(), cx));
let id = cx.derive_id(get_id_for_impl(cx.tcx(), i.impl_item.item_id));
let aliases = if aliases.is_empty() {
String::new()
} else {
@ -1994,21 +1995,35 @@ pub(crate) fn small_url_encode(s: String) -> String {
}
}
fn get_id_for_impl(for_: &clean::Type, trait_: Option<&clean::Path>, cx: &Context<'_>) -> String {
match trait_ {
Some(t) => small_url_encode(format!("impl-{:#}-for-{:#}", t.print(cx), for_.print(cx))),
None => small_url_encode(format!("impl-{:#}", for_.print(cx))),
}
fn get_id_for_impl<'tcx>(tcx: TyCtxt<'tcx>, impl_id: ItemId) -> String {
use rustc_middle::ty::print::with_forced_trimmed_paths;
let (type_, trait_) = match impl_id {
ItemId::Auto { trait_, for_ } => {
let ty = tcx.type_of(for_).skip_binder();
(ty, Some(ty::TraitRef::new(tcx, trait_, [ty])))
}
ItemId::Blanket { impl_id, .. } | ItemId::DefId(impl_id) => {
match tcx.impl_subject(impl_id).skip_binder() {
ty::ImplSubject::Trait(trait_ref) => {
(trait_ref.args[0].expect_ty(), Some(trait_ref))
}
ty::ImplSubject::Inherent(ty) => (ty, None),
}
}
};
with_forced_trimmed_paths!(small_url_encode(if let Some(trait_) = trait_ {
format!("impl-{trait_}-for-{type_}", trait_ = trait_.print_only_trait_path())
} else {
format!("impl-{type_}")
}))
}
fn extract_for_impl_name(item: &clean::Item, cx: &Context<'_>) -> Option<(String, String)> {
match *item.kind {
clean::ItemKind::ImplItem(ref i) => {
i.trait_.as_ref().map(|trait_| {
// Alternative format produces no URLs,
// so this parameter does nothing.
(format!("{:#}", i.for_.print(cx)), get_id_for_impl(&i.for_, Some(trait_), cx))
})
clean::ItemKind::ImplItem(ref i) if i.trait_.is_some() => {
// Alternative format produces no URLs,
// so this parameter does nothing.
Some((format!("{:#}", i.for_.print(cx)), get_id_for_impl(cx.tcx(), item.item_id)))
}
_ => None,
}

View file

@ -12,7 +12,7 @@ use crate::formats::cache::{Cache, OrphanImplItem};
use crate::formats::item_type::ItemType;
use crate::html::format::join_with_double_colon;
use crate::html::markdown::short_markdown_summary;
use crate::html::render::{IndexItem, IndexItemFunctionType, RenderType, RenderTypeId};
use crate::html::render::{self, IndexItem, IndexItemFunctionType, RenderType, RenderTypeId};
/// Builds the search index from the collected metadata
pub(crate) fn build_index<'tcx>(
@ -26,7 +26,8 @@ pub(crate) fn build_index<'tcx>(
// Attach all orphan items to the type's definition if the type
// has since been learned.
for &OrphanImplItem { parent, ref item, ref impl_generics } in &cache.orphan_impl_items {
for &OrphanImplItem { impl_id, parent, ref item, ref impl_generics } in &cache.orphan_impl_items
{
if let Some((fqp, _)) = cache.paths.get(&parent) {
let desc = short_markdown_summary(&item.doc_value(), &item.link_names(cache));
cache.search_index.push(IndexItem {
@ -36,6 +37,7 @@ pub(crate) fn build_index<'tcx>(
desc,
parent: Some(parent),
parent_idx: None,
impl_id,
search_type: get_function_type_for_search(item, tcx, impl_generics.as_ref(), cache),
aliases: item.attrs.get_doc_aliases(),
deprecation: item.deprecation(tcx),
@ -222,6 +224,29 @@ pub(crate) fn build_index<'tcx>(
})
.collect();
// Find associated items that need disambiguators
let mut associated_item_duplicates = FxHashMap::<(isize, ItemType, Symbol), usize>::default();
for &item in &crate_items {
if item.impl_id.is_some() && let Some(parent_idx) = item.parent_idx {
let count = associated_item_duplicates
.entry((parent_idx, item.ty, item.name))
.or_insert(0);
*count += 1;
}
}
let associated_item_disambiguators = crate_items
.iter()
.enumerate()
.filter_map(|(index, item)| {
let impl_id = ItemId::DefId(item.impl_id?);
let parent_idx = item.parent_idx?;
let count = *associated_item_duplicates.get(&(parent_idx, item.ty, item.name))?;
if count > 1 { Some((index, render::get_id_for_impl(tcx, impl_id))) } else { None }
})
.collect::<Vec<_>>();
struct CrateData<'a> {
doc: String,
items: Vec<&'a IndexItem>,
@ -230,6 +255,8 @@ pub(crate) fn build_index<'tcx>(
//
// To be noted: the `usize` elements are indexes to `items`.
aliases: &'a BTreeMap<String, Vec<usize>>,
// Used when a type has more than one impl with an associated item with the same name.
associated_item_disambiguators: &'a Vec<(usize, String)>,
}
struct Paths {
@ -382,6 +409,7 @@ pub(crate) fn build_index<'tcx>(
crate_data.serialize_field("f", &functions)?;
crate_data.serialize_field("c", &deprecated)?;
crate_data.serialize_field("p", &paths)?;
crate_data.serialize_field("b", &self.associated_item_disambiguators)?;
if has_aliases {
crate_data.serialize_field("a", &self.aliases)?;
}
@ -398,6 +426,7 @@ pub(crate) fn build_index<'tcx>(
items: crate_items,
paths: crate_paths,
aliases: &aliases,
associated_item_disambiguators: &associated_item_disambiguators,
})
.expect("failed serde conversion")
// All these `replace` calls are because we have to go through JS string for JSON content.

View file

@ -503,8 +503,7 @@ fn sidebar_render_assoc_items(
.iter()
.filter_map(|it| {
let trait_ = it.inner_impl().trait_.as_ref()?;
let encoded =
id_map.derive(super::get_id_for_impl(&it.inner_impl().for_, Some(trait_), cx));
let encoded = id_map.derive(super::get_id_for_impl(cx.tcx(), it.impl_item.item_id));
let prefix = match it.inner_impl().polarity {
ty::ImplPolarity::Positive | ty::ImplPolarity::Reservation => "",

View file

@ -354,6 +354,34 @@ function preLoadCss(cssUrl) {
expandSection(pageId);
}
}
if (savedHash.startsWith("impl-")) {
// impl-disambiguated links, used by the search engine
// format: impl-X[-for-Y]/method.WHATEVER
// turn this into method.WHATEVER[-NUMBER]
const splitAt = savedHash.indexOf("/");
if (splitAt !== -1) {
const implId = savedHash.slice(0, splitAt);
const assocId = savedHash.slice(splitAt + 1);
const implElem = document.getElementById(implId);
if (implElem && implElem.parentElement.tagName === "SUMMARY" &&
implElem.parentElement.parentElement.tagName === "DETAILS") {
onEachLazy(implElem.parentElement.parentElement.querySelectorAll(
`[id^="${assocId}"]`),
item => {
const numbered = /([^-]+)-([0-9]+)/.exec(item.id);
if (item.id === assocId || (numbered && numbered[1] === assocId)) {
openParentDetails(item);
item.scrollIntoView();
// Let the section expand itself before trying to highlight
setTimeout(() => {
window.location.replace("#" + item.id);
}, 0);
}
}
);
}
}
}
}
function onHashChange(ev) {

View file

@ -1752,6 +1752,7 @@ function initSearch(rawSearchIndex) {
type: item.type,
is_alias: true,
deprecated: item.deprecated,
implDisambiguator: item.implDisambiguator,
};
}
@ -2218,7 +2219,7 @@ function initSearch(rawSearchIndex) {
href = ROOT_PATH + name + "/index.html";
} else if (item.parent !== undefined) {
const myparent = item.parent;
let anchor = "#" + type + "." + name;
let anchor = type + "." + name;
const parentType = itemTypes[myparent.ty];
let pageType = parentType;
let pageName = myparent.name;
@ -2232,16 +2233,19 @@ function initSearch(rawSearchIndex) {
const enumName = item.path.substr(enumNameIdx + 2);
path = item.path.substr(0, enumNameIdx);
displayPath = path + "::" + enumName + "::" + myparent.name + "::";
anchor = "#variant." + myparent.name + ".field." + name;
anchor = "variant." + myparent.name + ".field." + name;
pageType = "enum";
pageName = enumName;
} else {
displayPath = path + "::" + myparent.name + "::";
}
if (item.implDisambiguator !== null) {
anchor = item.implDisambiguator + "/" + anchor;
}
href = ROOT_PATH + path.replace(/::/g, "/") +
"/" + pageType +
"." + pageName +
".html" + anchor;
".html#" + anchor;
} else {
displayPath = item.path + "::";
href = ROOT_PATH + item.path.replace(/::/g, "/") +
@ -2727,6 +2731,10 @@ ${item.displayPath}<span class="${type}">${name}</span>\
* Types are also represented as arrays; the first item is an index into the `p`
* array, while the second is a list of types representing any generic parameters.
*
* b[i] contains an item's impl disambiguator. This is only present if an item
* is defined in an impl block and, the impl block's type has more than one associated
* item with the same name.
*
* `a` defines aliases with an Array of pairs: [name, offset], where `offset`
* points into the n/t/d/q/i/f arrays.
*
@ -2746,6 +2754,7 @@ ${item.displayPath}<span class="${type}">${name}</span>\
* i: Array<Number>,
* f: Array<RawFunctionSearchType>,
* p: Array<Object>,
* b: Array<[Number, String]>,
* c: Array<Number>
* }}
*/
@ -2766,6 +2775,7 @@ ${item.displayPath}<span class="${type}">${name}</span>\
id: id,
normalizedName: crate.indexOf("_") === -1 ? crate : crate.replace(/_/g, ""),
deprecated: null,
implDisambiguator: null,
};
id += 1;
searchIndex.push(crateRow);
@ -2789,6 +2799,8 @@ ${item.displayPath}<span class="${type}">${name}</span>\
const itemFunctionSearchTypes = crateCorpus.f;
// an array of (Number) indices for the deprecated items
const deprecatedItems = new Set(crateCorpus.c);
// an array of (Number) indices for the deprecated items
const implDisambiguator = new Map(crateCorpus.b);
// an array of [(Number) item type,
// (String) name]
const paths = crateCorpus.p;
@ -2849,6 +2861,7 @@ ${item.displayPath}<span class="${type}">${name}</span>\
id: id,
normalizedName: word.indexOf("_") === -1 ? word : word.replace(/_/g, ""),
deprecated: deprecatedItems.has(i),
implDisambiguator: implDisambiguator.has(i) ? implDisambiguator.get(i) : null,
};
id += 1;
searchIndex.push(row);

View file

@ -0,0 +1,43 @@
// ignore-tidy-linelength
// Checks that, if a type has two methods with the same name, they both get
// linked correctly.
go-to: "file://" + |DOC_PATH| + "/test_docs/index.html"
// This should link to the inherent impl
write: (".search-input", "ZyxwvutMethodDisambiguation -> bool")
// To be SURE that the search will be run.
press-key: 'Enter'
// Waiting for the search results to appear...
wait-for: "#search-tabs"
// Check the disambiguated link.
assert-count: ("a.result-method", 1)
assert-attribute: ("a.result-method", {
"href": "../test_docs/struct.ZyxwvutMethodDisambiguation.html#impl-ZyxwvutMethodDisambiguation/method.method_impl_disambiguation"
})
click: "a.result-method"
wait-for: "#impl-ZyxwvutMethodDisambiguation"
assert-document-property: ({
"URL": "struct.ZyxwvutMethodDisambiguation.html#method.method_impl_disambiguation"
}, ENDS_WITH)
assert: "section:target"
go-to: "file://" + |DOC_PATH| + "/test_docs/index.html"
// This should link to the trait impl
write: (".search-input", "ZyxwvutMethodDisambiguation, usize -> usize")
// To be SURE that the search will be run.
press-key: 'Enter'
// Waiting for the search results to appear...
wait-for: "#search-tabs"
// Check the disambiguated link.
assert-count: ("a.result-method", 1)
assert-attribute: ("a.result-method", {
"href": "../test_docs/struct.ZyxwvutMethodDisambiguation.html#impl-ZyxwvutTrait-for-ZyxwvutMethodDisambiguation/method.method_impl_disambiguation"
})
click: "a.result-method"
wait-for: "#impl-ZyxwvutMethodDisambiguation"
assert-document-property: ({
"URL": "struct.ZyxwvutMethodDisambiguation.html#method.method_impl_disambiguation-1"
}, ENDS_WITH)
assert: "section:target"

View file

@ -529,3 +529,21 @@ pub mod cfgs {
/// Some docs.
pub mod cfgs {}
}
pub struct ZyxwvutMethodDisambiguation;
impl ZyxwvutMethodDisambiguation {
pub fn method_impl_disambiguation(&self) -> bool {
true
}
}
pub trait ZyxwvutTrait {
fn method_impl_disambiguation(&self, x: usize) -> usize;
}
impl ZyxwvutTrait for ZyxwvutMethodDisambiguation {
fn method_impl_disambiguation(&self, x: usize) -> usize {
x
}
}

View file

@ -0,0 +1,70 @@
// exact-check
// ignore-order
// ignore-tidy-linelength
// This test case verifies that the href points at the correct impl
const FILTER_CRATE = "std";
const EXPECTED = [
{
'query': 'simd<i16>, simd<i16> -> simd<i16>',
'others': [
{
'path': 'std::simd::prelude::Simd',
'name': 'simd_max',
'href': '../std/simd/prelude/struct.Simd.html#impl-SimdOrd-for-Simd%3Ci16,+LANES%3E/method.simd_max'
},
{
'path': 'std::simd::prelude::Simd',
'name': 'simd_min',
'href': '../std/simd/prelude/struct.Simd.html#impl-SimdOrd-for-Simd%3Ci16,+LANES%3E/method.simd_min'
},
{
'path': 'std::simd::prelude::Simd',
'name': 'simd_clamp',
'href': '../std/simd/prelude/struct.Simd.html#impl-SimdOrd-for-Simd%3Ci16,+LANES%3E/method.simd_clamp'
},
{
'path': 'std::simd::prelude::Simd',
'name': 'saturating_add',
'href': '../std/simd/prelude/struct.Simd.html#impl-SimdInt-for-Simd%3Ci16,+LANES%3E/method.saturating_add'
},
{
'path': 'std::simd::prelude::Simd',
'name': 'saturating_sub',
'href': '../std/simd/prelude/struct.Simd.html#impl-SimdInt-for-Simd%3Ci16,+LANES%3E/method.saturating_sub'
},
],
},
{
'query': 'simd<i8>, simd<i8> -> simd<i8>',
'others': [
{
'path': 'std::simd::prelude::Simd',
'name': 'simd_max',
'href': '../std/simd/prelude/struct.Simd.html#impl-SimdOrd-for-Simd%3Ci8,+LANES%3E/method.simd_max'
},
{
'path': 'std::simd::prelude::Simd',
'name': 'simd_min',
'href': '../std/simd/prelude/struct.Simd.html#impl-SimdOrd-for-Simd%3Ci8,+LANES%3E/method.simd_min'
},
{
'path': 'std::simd::prelude::Simd',
'name': 'simd_clamp',
'href': '../std/simd/prelude/struct.Simd.html#impl-SimdOrd-for-Simd%3Ci8,+LANES%3E/method.simd_clamp'
},
{
'path': 'std::simd::prelude::Simd',
'name': 'saturating_add',
'href': '../std/simd/prelude/struct.Simd.html#impl-SimdInt-for-Simd%3Ci8,+LANES%3E/method.saturating_add'
},
{
'path': 'std::simd::prelude::Simd',
'name': 'saturating_sub',
'href': '../std/simd/prelude/struct.Simd.html#impl-SimdInt-for-Simd%3Ci8,+LANES%3E/method.saturating_sub'
},
],
},
];

View file

@ -0,0 +1,28 @@
// exact-check
// ignore-order
// ignore-tidy-linelength
const FILTER_CRATE = "search_method_disambiguate";
const EXPECTED = [
{
'query': 'MyTy -> bool',
'others': [
{
'path': 'search_method_disambiguate::MyTy',
'name': 'my_method',
'href': '../search_method_disambiguate/struct.MyTy.html#impl-X-for-MyTy%3Cbool%3E/method.my_method'
},
],
},
{
'query': 'MyTy -> u8',
'others': [
{
'path': 'search_method_disambiguate::MyTy',
'name': 'my_method',
'href': '../search_method_disambiguate/struct.MyTy.html#impl-X-for-MyTy%3Cu8%3E/method.my_method'
},
],
}
];

View file

@ -0,0 +1,22 @@
pub trait X {
type InnerType;
fn my_method(&self) -> Self::InnerType;
}
pub struct MyTy<T> {
pub t: T,
}
impl X for MyTy<bool> {
type InnerType = bool;
fn my_method(&self) -> bool {
self.t
}
}
impl X for MyTy<u8> {
type InnerType = u8;
fn my_method(&self) -> u8 {
self.t
}
}

View file

@ -1,6 +1,6 @@
#![crate_name = "foo"]
// @has foo/struct.S.html '//*[@id="impl-Into%3CU%3E-for-S"]//h3[@class="code-header"]' 'impl<T, U> Into<U> for T'
// @has foo/struct.S.html '//*[@id="impl-Into%3CU%3E-for-T"]//h3[@class="code-header"]' 'impl<T, U> Into<U> for T'
pub struct S2 {}
mod m {
pub struct S {}

View file

@ -31,7 +31,7 @@ impl<T> VSet<T, { Order::Unsorted }> {
pub struct Escape<const S: &'static str>;
// @has foo/struct.Escape.html '//*[@id="impl-Escape%3Cr%23%22%3Cscript%3Ealert(%22Escape%22);%3C/script%3E%22%23%3E"]/h3[@class="code-header"]' 'impl Escape<r#"<script>alert("Escape");</script>"#>'
// @has foo/struct.Escape.html '//*[@id="impl-Escape%3C%22%3Cscript%3Ealert(%5C%22Escape%5C%22);%3C/script%3E%22%3E"]/h3[@class="code-header"]' 'impl Escape<r#"<script>alert("Escape");</script>"#>'
impl Escape<r#"<script>alert("Escape");</script>"#> {
pub fn f() {}
}

View file

@ -5,9 +5,9 @@ use std::fmt;
// @!has foo/struct.Bar.html '//*[@id="impl-ToString-for-Bar"]' ''
pub struct Bar;
// @has foo/struct.Foo.html '//*[@id="impl-ToString-for-Foo"]//h3[@class="code-header"]' 'impl<T> ToString for T'
// @has foo/struct.Foo.html '//*[@id="impl-ToString-for-T"]//h3[@class="code-header"]' 'impl<T> ToString for T'
pub struct Foo;
// @has foo/struct.Foo.html '//*[@class="sidebar-elems"]//section//a[@href="#impl-ToString-for-Foo"]' 'ToString'
// @has foo/struct.Foo.html '//*[@class="sidebar-elems"]//section//a[@href="#impl-ToString-for-T"]' 'ToString'
impl fmt::Display for Foo {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {

View file

@ -22,7 +22,7 @@ impl Bar for GenericStruct<u32> {}
// We check that "Aliased type" is also present as a title in the sidebar.
// @has - '//*[@class="sidebar-elems"]//h3/a[@href="#aliased-type"]' 'Aliased type'
// We check that we have the implementation of the type alias itself.
// @has - '//*[@id="impl-TypedefStruct"]/h3' 'impl TypedefStruct'
// @has - '//*[@id="impl-GenericStruct%3Cu8%3E"]/h3' 'impl TypedefStruct'
// @has - '//*[@id="method.on_alias"]/h4' 'pub fn on_alias()'
// @has - '//*[@id="impl-GenericStruct%3CT%3E"]/h3' 'impl<T> GenericStruct<T>'
// @has - '//*[@id="method.on_gen"]/h4' 'pub fn on_gen(arg: T)'

View file

@ -6,7 +6,7 @@
// @has 'foo/struct.AnotherStruct.html'
// @count - '//*[@class="sidebar"]//a[@href="#impl-AnAmazingTrait-for-AnotherStruct%3C()%3E"]' 1
// @count - '//*[@class="sidebar"]//a[@href="#impl-AnAmazingTrait-for-AnotherStruct%3CT%3E"]' 1
// @count - '//*[@class="sidebar"]//a[@href="#impl-AnAmazingTrait-for-T"]' 1
pub trait Something {}

View file

@ -1,7 +1,7 @@
#![feature(rustc_attrs)]
#![crate_name = "foo"]
// @has foo/primitive.i32.html '//*[@id="impl-ToString-for-i32"]//h3[@class="code-header"]' 'impl<T> ToString for T'
// @has foo/primitive.i32.html '//*[@id="impl-ToString-for-T"]//h3[@class="code-header"]' 'impl<T> ToString for T'
#[rustc_doc_primitive = "i32"]
/// Some useless docs, wouhou!

View file

@ -7,8 +7,8 @@
// @has - '//h2[@id="foreign-impls"]' 'Implementations on Foreign Types'
// @has - '//*[@class="sidebar-elems"]//section//a[@href="#impl-Foo-for-u32"]' 'u32'
// @has - '//*[@id="impl-Foo-for-u32"]//h3[@class="code-header"]' 'impl Foo for u32'
// @has - "//*[@class=\"sidebar-elems\"]//section//a[@href=\"#impl-Foo-for-%26'a+str\"]" "&'a str"
// @has - "//*[@id=\"impl-Foo-for-%26'a+str\"]//h3[@class=\"code-header\"]" "impl<'a> Foo for &'a str"
// @has - "//*[@class=\"sidebar-elems\"]//section//a[@href=\"#impl-Foo-for-%26str\"]" "&'a str"
// @has - "//*[@id=\"impl-Foo-for-%26str\"]//h3[@class=\"code-header\"]" "impl<'a> Foo for &'a str"
pub trait Foo {}
impl Foo for u32 {}

View file

@ -5,8 +5,8 @@
// @!has - '//*[@id="impl-Sized-for-Unsized"]//a[@class="src"]' 'source'
// @has - '//*[@id="impl-Sync-for-Unsized"]/h3[@class="code-header"]' 'impl Sync for Unsized'
// @!has - '//*[@id="impl-Sync-for-Unsized"]//a[@class="src"]' 'source'
// @has - '//*[@id="impl-Any-for-Unsized"]/h3[@class="code-header"]' 'impl<T> Any for T'
// @has - '//*[@id="impl-Any-for-Unsized"]//a[@class="src rightside"]' 'source'
// @has - '//*[@id="impl-Any-for-T"]/h3[@class="code-header"]' 'impl<T> Any for T'
// @has - '//*[@id="impl-Any-for-T"]//a[@class="src rightside"]' 'source'
pub struct Unsized {
data: [u8],
}

View file

@ -7,7 +7,7 @@ where
}
// @has 'foo/trait.SomeTrait.html'
// @has - "//*[@id='impl-SomeTrait%3C(A,+B,+C,+D,+E)%3E-for-(A,+B,+C,+D,+E)']/h3" "impl<A, B, C, D, E> SomeTrait<(A, B, C, D, E)> for (A, B, C, D, E)where A: PartialOrd<A> + PartialEq<A>, B: PartialOrd<B> + PartialEq<B>, C: PartialOrd<C> + PartialEq<C>, D: PartialOrd<D> + PartialEq<D>, E: PartialOrd<E> + PartialEq<E> + ?Sized, "
// @has - "//*[@id='impl-SomeTrait-for-(A,+B,+C,+D,+E)']/h3" "impl<A, B, C, D, E> SomeTrait<(A, B, C, D, E)> for (A, B, C, D, E)where A: PartialOrd<A> + PartialEq<A>, B: PartialOrd<B> + PartialEq<B>, C: PartialOrd<C> + PartialEq<C>, D: PartialOrd<D> + PartialEq<D>, E: PartialOrd<E> + PartialEq<E> + ?Sized, "
impl<A, B, C, D, E> SomeTrait<(A, B, C, D, E)> for (A, B, C, D, E)
where
A: PartialOrd<A> + PartialEq<A>,
@ -17,3 +17,14 @@ where
E: PartialOrd<E> + PartialEq<E> + ?Sized,
{
}
// @has - "//*[@id='impl-SomeTrait%3C(A,+B,+C,+D)%3E-for-(A,+B,+C,+D,+E)']/h3" "impl<A, B, C, D, E> SomeTrait<(A, B, C, D)> for (A, B, C, D, E)where A: PartialOrd<A> + PartialEq<A>, B: PartialOrd<B> + PartialEq<B>, C: PartialOrd<C> + PartialEq<C>, D: PartialOrd<D> + PartialEq<D>, E: PartialOrd<E> + PartialEq<E> + ?Sized, "
impl<A, B, C, D, E> SomeTrait<(A, B, C, D)> for (A, B, C, D, E)
where
A: PartialOrd<A> + PartialEq<A>,
B: PartialOrd<B> + PartialEq<B>,
C: PartialOrd<C> + PartialEq<C>,
D: PartialOrd<D> + PartialEq<D>,
E: PartialOrd<E> + PartialEq<E> + ?Sized,
{
}

View file

@ -0,0 +1,20 @@
// build-fail
// compile-flags: -O
//! Make sure we detect erroneous constants post-monomorphization even when they are unused. This is
//! crucial, people rely on it for soundness. (https://github.com/rust-lang/rust/issues/112090)
struct PrintName<T>(T);
impl<T> PrintName<T> {
const VOID: () = panic!(); //~ERROR evaluation of `PrintName::<i32>::VOID` failed
}
fn no_codegen<T>() {
// Any function that is called is guaranteed to have all consts that syntactically
// appear in its body evaluated, even if they only appear in dead code.
if false {
let _ = PrintName::<T>::VOID;
}
}
pub fn main() {
no_codegen::<i32>();
}

View file

@ -0,0 +1,11 @@
error[E0080]: evaluation of `PrintName::<i32>::VOID` failed
--> $DIR/unused-broken-const-late.rs:8:22
|
LL | const VOID: () = panic!();
| ^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/unused-broken-const-late.rs:8:22
|
= note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to previous error
For more information about this error, try `rustc --explain E0080`.

View file

@ -1,7 +1,35 @@
use std::ops::FnMut;
pub fn main() {
fn main() {
let mut f = |x: isize, y: isize| -> isize { x + y };
let z = f(1_usize, 2); //~ ERROR mismatched types
let z = f(1_usize, 2); //~ ERROR mismatched types
println!("{}", z);
let mut g = |x, y| { x + y };
let y = g(1_i32, 2);
let z = g(1_usize, 2); //~ ERROR mismatched types
println!("{}", z);
}
trait T {
fn bar(&self) {
let identity = |x| x;
identity(1u8);
identity(1u16); //~ ERROR mismatched types
let identity = |x| x;
identity(&1u8);
identity(&1u16); //~ ERROR mismatched types
}
}
struct S;
impl T for S {
fn bar(&self) {
let identity = |x| x;
identity(1u8);
identity(1u16); //~ ERROR mismatched types
let identity = |x| x;
identity(&1u8);
identity(&1u16); //~ ERROR mismatched types
}
}

View file

@ -16,6 +16,127 @@ help: change the type of the numeric literal from `usize` to `isize`
LL | let z = f(1_isize, 2);
| ~~~~~
error: aborting due to previous error
error[E0308]: mismatched types
--> $DIR/unboxed-closures-type-mismatch.rs:9:15
|
LL | let z = g(1_usize, 2);
| - ^^^^^^^ expected `i32`, found `usize`
| |
| arguments to this function are incorrect
|
note: expected because the closure was earlier called with an argument of type `i32`
--> $DIR/unboxed-closures-type-mismatch.rs:8:15
|
LL | let y = g(1_i32, 2);
| - ^^^^^ expected because this argument is of type `i32`
| |
| in this closure call
note: closure parameter defined here
--> $DIR/unboxed-closures-type-mismatch.rs:7:18
|
LL | let mut g = |x, y| { x + y };
| ^
help: change the type of the numeric literal from `usize` to `i32`
|
LL | let z = g(1_i32, 2);
| ~~~
error[E0308]: mismatched types
--> $DIR/unboxed-closures-type-mismatch.rs:17:18
|
LL | identity(1u16);
| -------- ^^^^ expected `u8`, found `u16`
| |
| arguments to this function are incorrect
|
note: expected because the closure was earlier called with an argument of type `u8`
--> $DIR/unboxed-closures-type-mismatch.rs:16:18
|
LL | identity(1u8);
| -------- ^^^ expected because this argument is of type `u8`
| |
| in this closure call
note: closure parameter defined here
--> $DIR/unboxed-closures-type-mismatch.rs:15:25
|
LL | let identity = |x| x;
| ^
help: change the type of the numeric literal from `u16` to `u8`
|
LL | identity(1u8);
| ~~
error[E0308]: mismatched types
--> $DIR/unboxed-closures-type-mismatch.rs:20:18
|
LL | identity(&1u16);
| -------- ^^^^^ expected `&u8`, found `&u16`
| |
| arguments to this function are incorrect
|
= note: expected reference `&u8`
found reference `&u16`
note: expected because the closure was earlier called with an argument of type `&u8`
--> $DIR/unboxed-closures-type-mismatch.rs:19:18
|
LL | identity(&1u8);
| -------- ^^^^ expected because this argument is of type `&u8`
| |
| in this closure call
note: closure parameter defined here
--> $DIR/unboxed-closures-type-mismatch.rs:18:25
|
LL | let identity = |x| x;
| ^
error[E0308]: mismatched types
--> $DIR/unboxed-closures-type-mismatch.rs:30:18
|
LL | identity(1u16);
| -------- ^^^^ expected `u8`, found `u16`
| |
| arguments to this function are incorrect
|
note: expected because the closure was earlier called with an argument of type `u8`
--> $DIR/unboxed-closures-type-mismatch.rs:29:18
|
LL | identity(1u8);
| -------- ^^^ expected because this argument is of type `u8`
| |
| in this closure call
note: closure parameter defined here
--> $DIR/unboxed-closures-type-mismatch.rs:28:25
|
LL | let identity = |x| x;
| ^
help: change the type of the numeric literal from `u16` to `u8`
|
LL | identity(1u8);
| ~~
error[E0308]: mismatched types
--> $DIR/unboxed-closures-type-mismatch.rs:33:18
|
LL | identity(&1u16);
| -------- ^^^^^ expected `&u8`, found `&u16`
| |
| arguments to this function are incorrect
|
= note: expected reference `&u8`
found reference `&u16`
note: expected because the closure was earlier called with an argument of type `&u8`
--> $DIR/unboxed-closures-type-mismatch.rs:32:18
|
LL | identity(&1u8);
| -------- ^^^^ expected because this argument is of type `&u8`
| |
| in this closure call
note: closure parameter defined here
--> $DIR/unboxed-closures-type-mismatch.rs:31:25
|
LL | let identity = |x| x;
| ^
error: aborting due to 6 previous errors
For more information about this error, try `rustc --explain E0308`.