Skip to content

Commit cf3972e

Browse files
committed
librustc: Propagate type uses correctly from method calls to the containing functions. rs=bugfix
This adds a new script, `monodebug.pl`. It can be used to diagnose problems stemming from incorrect combining of monomorphic generic instantiations.
1 parent ddfd1ea commit cf3972e

File tree

2 files changed

+84
-4
lines changed

2 files changed

+84
-4
lines changed

src/etc/monodebug.pl

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
#!/usr/bin/perl
2+
3+
#
4+
# This is a tool that helps with debugging incorrect monomorphic instance collapse.
5+
#
6+
# To use:
7+
# $ RUST_LOG=rustc::middle::trans::monomorphize rustc ARGS 2>&1 >log.txt
8+
# $ ./monodebug.pl log.txt
9+
#
10+
# This will show all generics that got collapsed. You can inspect this list to find the instances
11+
# that were mistakenly combined into one. Fixes will (most likely) be applied to type_use.rs.
12+
#
13+
# Questions about this tool go to pcwalton.
14+
#
15+
16+
use strict;
17+
use warnings;
18+
use Data::Dumper qw(Dumper);
19+
use Text::Balanced qw(extract_bracketed);
20+
21+
my %funcs;
22+
while (<>) {
23+
chomp;
24+
/^rust: ~"monomorphic_fn\((.*)"$/ or next;
25+
my $text = $1;
26+
$text =~ /fn_id=(\{ crate: \d+, node: \d+ \} \([^)]+\)), real_substs=(.*?), substs=(.*?), hash_id = \@\{ (.*) \}$/ or next;
27+
my ($fn_id, $real_substs, $substs, $hash_id) = ($1, $2, $3, $4);
28+
29+
#print "$hash_id\n";
30+
$hash_id =~ /^def: { crate: \d+, node: \d+ }, params: ~\[ (.*) \], impl_did_opt: (?:None|Some\({ crate: \d+, node: \d+ }\))$/ or next;
31+
my $params = $1;
32+
33+
my @real_substs;
34+
@real_substs = $real_substs =~ /\\"(.*?)\\"/g;
35+
36+
my @mono_params;
37+
while (1) {
38+
$params =~ s/^, //;
39+
if ($params =~ s/^mono_precise//) {
40+
extract_bracketed($params, '()');
41+
push @mono_params, 'precise';
42+
next;
43+
}
44+
if ($params =~ s/^mono_repr//) {
45+
my $sub = extract_bracketed($params, '()');
46+
push @mono_params, "repr($sub)";
47+
next;
48+
}
49+
if ($params =~ s/^mono_any//) {
50+
push @mono_params, "any";
51+
next;
52+
}
53+
last;
54+
}
55+
56+
my @key_params;
57+
for (my $i = 0; $i < @mono_params; ++$i) {
58+
if ($mono_params[$i] eq 'precise') {
59+
push @key_params, 'precise(' . $real_substs[$i] . ')';
60+
} else {
61+
push @key_params, $mono_params[$i];
62+
}
63+
}
64+
65+
my $key = "$fn_id with " . (join ', ', @key_params);
66+
$funcs{$key}{$real_substs} = 1;
67+
}
68+
69+
while (my ($key, $substs) = each %funcs) {
70+
my @params = keys %$substs;
71+
next if @params == 1;
72+
73+
print "$key\n";
74+
print(('-' x (length $key)), $/);
75+
for my $param (@params) {
76+
print "$param\n";
77+
}
78+
print "\n";
79+
}
80+

src/librustc/middle/trans/type_use.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -192,11 +192,11 @@ fn node_type_needs(cx: ctx, use_: uint, id: node_id) {
192192
type_needs(cx, use_, ty::node_id_to_type(cx.ccx.tcx, id));
193193
}
194194

195-
fn mark_for_method_call(cx: ctx, e_id: node_id) {
195+
fn mark_for_method_call(cx: ctx, e_id: node_id, callee_id: node_id) {
196196
do option::iter(&cx.ccx.maps.method_map.find(e_id)) |mth| {
197197
match mth.origin {
198198
typeck::method_static(did) => {
199-
do cx.ccx.tcx.node_type_substs.find(e_id).iter |ts| {
199+
do cx.ccx.tcx.node_type_substs.find(callee_id).iter |ts| {
200200
let type_uses = type_uses_for(cx.ccx, did, ts.len());
201201
for vec::each2(type_uses, *ts) |uses, subst| {
202202
type_needs(cx, *uses, *subst)
@@ -269,7 +269,7 @@ fn mark_for_expr(cx: ctx, e: @expr) {
269269
// the chosen field.
270270
let base_ty = ty::node_id_to_type(cx.ccx.tcx, base.id);
271271
type_needs(cx, use_repr, ty::type_autoderef(cx.ccx.tcx, base_ty));
272-
mark_for_method_call(cx, e.id);
272+
mark_for_method_call(cx, e.id, e.callee_id);
273273
}
274274
expr_log(_, _, val) => {
275275
node_type_needs(cx, use_tydesc, val.id);
@@ -299,7 +299,7 @@ fn mark_for_expr(cx: ctx, e: @expr) {
299299
_ => ()
300300
}
301301
}
302-
mark_for_method_call(cx, e.id);
302+
mark_for_method_call(cx, e.id, e.callee_id);
303303
}
304304
expr_paren(e) => mark_for_expr(cx, e),
305305
expr_match(*) | expr_block(_) | expr_if(*) |

0 commit comments

Comments
 (0)